diff --git a/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/AuthLib.proj b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/AuthLib.proj new file mode 100644 index 0000000000..8186f7eea4 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/AuthLib.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/BlowFish.c b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/BlowFish.c new file mode 100644 index 0000000000..789eab32a9 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/BlowFish.c @@ -0,0 +1,189 @@ +/* blowfish.c */ + +#include "BlowFish.h" +#include "BlowFishTable.h" + +#define N 16 +#define noErr 0 +#define DATAERROR -1 +#define KEYBYTES 8 + +unsigned long F(blf_ctx *bc, unsigned long x) +{ + unsigned long a; + unsigned long b; + unsigned long c; + unsigned long d; + unsigned long y; + + d = x & 0x00FF; + x >>= 8; + c = x & 0x00FF; + x >>= 8; + b = x & 0x00FF; + x >>= 8; + a = x & 0x00FF; + y = bc->S[0][a] + bc->S[1][b]; + y = y ^ bc->S[2][c]; + y = y + bc->S[3][d]; + + return y; +} + +void Blowfish_encipher(blf_ctx *bc, unsigned long *xl, unsigned long *xr) +{ + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = 0; i < N; ++i) + { + Xl = Xl ^ bc->P[i]; + Xr = F(bc, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ bc->P[N]; + Xl = Xl ^ bc->P[N + 1]; + + *xl = Xl; + *xr = Xr; +} + +void Blowfish_decipher(blf_ctx *bc, unsigned long *xl, unsigned long *xr) +{ + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = N + 1; i > 1; --i) + { + Xl = Xl ^ bc->P[i]; + Xr = F(bc, Xl) ^ Xr; + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + } + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ bc->P[1]; + Xl = Xl ^ bc->P[0]; + + *xl = Xl; + *xr = Xr; +} + +short InitializeBlowfish(blf_ctx *bc, unsigned char key[], int keybytes) +{ + short i; + short j; + short k; + unsigned long data; + unsigned long datal; + unsigned long datar; + + /* initialise p & s-boxes without file read */ + for (i = 0; i < N+2; i++) + { + bc->P[i] = bfp[i]; + } + for (i = 0; i < 256; i++) + { + bc->S[0][i] = ks0[i]; + bc->S[1][i] = ks1[i]; + bc->S[2][i] = ks2[i]; + bc->S[3][i] = ks3[i]; + } + + j = 0; + for (i = 0; i < N + 2; ++i) + { + data = 0x00000000; + for (k = 0; k < 4; ++k) + { + data = (data << 8) | key[j]; + j = j + 1; + if (j >= keybytes) + { + j = 0; + } + } + bc->P[i] = bc->P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for (i = 0; i < N + 2; i += 2) + { + Blowfish_encipher(bc, &datal, &datar); + + bc->P[i] = datal; + bc->P[i + 1] = datar; + } + + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 256; j += 2) + { + + Blowfish_encipher(bc, &datal, &datar); + + bc->S[i][j] = datal; + bc->S[i][j + 1] = datar; + } + } + return 0; +} + +void blf_key (blf_ctx *c, unsigned char *k, int len) +{ + InitializeBlowfish(c, k, len); +} + +void blf_enc(blf_ctx *c, unsigned long *data, int blocks) +{ + unsigned long *d; + int i; + + d = data; + for (i = 0; i < blocks; i++) + { + Blowfish_encipher(c, d, d+1); + d += 2; + } +} + +void blf_dec(blf_ctx *c, unsigned long *data, int blocks) +{ + unsigned long *d; + int i; + + d = data; + for (i = 0; i < blocks; i++) + { + Blowfish_decipher(c, d, d+1); + d += 2; + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/BlowFish.h b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/BlowFish.h new file mode 100644 index 0000000000..cfc5667dd3 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/BlowFish.h @@ -0,0 +1,35 @@ +/* blowfish.h */ + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +#define UWORD32 unsigned long +#define UBYTE08 unsigned char + +#define MAXKEYBYTES 56 /* 448 bits */ + +typedef struct +{ + unsigned long S[4][256], P[18]; +} blf_ctx; + +unsigned long F(blf_ctx *, unsigned long x); +void Blowfish_encipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +void Blowfish_decipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +short InitializeBlowfish(blf_ctx *, unsigned char key[], int keybytes); + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE void blf_enc(blf_ctx *c, unsigned long *data, int blocks); +_IMPEXP_BESURE void blf_dec(blf_ctx *c, unsigned long *data, int blocks); +_IMPEXP_BESURE void blf_key(blf_ctx *c, unsigned char *key, int len); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/BlowFishTable.h b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/BlowFishTable.h new file mode 100644 index 0000000000..3547ee1d19 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/BlowFishTable.h @@ -0,0 +1,280 @@ +/* bf_tab.h: Blowfish P-box and S-box tables */ + + +static UWORD32 bfp[] = +{ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b, +}; + +static UWORD32 ks0[] = +{ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + }; + static UWORD32 ks1[]= + { + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 +}; +static UWORD32 ks2[] = +{ + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 +}; +static UWORD32 ks3[] = +{ + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/besure_auth.c b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/besure_auth.c new file mode 100644 index 0000000000..cccb6b3c1e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/besure_auth.c @@ -0,0 +1,907 @@ +#define _BUILDING_BESURE_ + +#include "FindDirectory.h" + +#include "betalk.h" +#include "sysdepdefs.h" +#include "besure_auth.h" +#include "md5.h" + +#include "netdb.h" +#include "utime.h" +#include "ctype.h" +#include "time.h" +#include "signal.h" +#include "stdlib.h" +#include "errno.h" +#include "socket.h" +#include "signal.h" +#include "stdio.h" + +typedef struct +{ + char *key; + char *value; + int valLength; +} key_value; + + +static uint32 genUniqueId(char *str); +static void strlwr(char *str); +static void removeFiles(char *folder, char *file); +static void recvAlarm(int signal); +static key_value *GetNextKey(FILE *fp); +static void FreeKeyValue(key_value *kv); +static int32 queryServers(void *data); + + +bool addUserToGroup(char *user, char *group) +{ + char userPath[B_PATH_NAME_LENGTH], groupPath[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, userPath, sizeof(userPath)); + strcpy(groupPath, userPath); + strcat(userPath, "/domains/default/users/"); + strcat(userPath, user); + strcat(groupPath, "/domains/default/groups/"); + strcat(groupPath, group); + strcat(groupPath, "/"); + strcat(groupPath, user); + + strlwr(userPath); + strlwr(groupPath); + + if (symlink(userPath, groupPath) == -1) + return false; + + return true; +} + +bool removeUserFromGroup(char *user, char *group) +{ + char userPath[B_PATH_NAME_LENGTH]; + + strlwr(user); + strlwr(group); + + // You can't remove someone from the group "everyone" -- sorry. + if (strcmp(group, "everyone") == 0) + return false; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, userPath, sizeof(userPath)); + strcat(userPath, "/domains/default/groups/"); + strcat(userPath, group); + strcat(userPath, "/"); + strcat(userPath, user); + + remove(userPath); + + return true; +} + +bool isUserInGroup(char *user, char *group) +{ + char userPath[B_PATH_NAME_LENGTH]; + + strlwr(user); + strlwr(group); + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, userPath, sizeof(userPath)); + strcat(userPath, "/domains/default/groups/"); + strcat(userPath, group); + strcat(userPath, "/"); + strcat(userPath, user); + + return (access(userPath, 0) == 0); +} + +bool createUser(char *user, char *password) +{ + char path[B_PATH_NAME_LENGTH]; + uint32 userID; + + // All usernames are saved in lowercase. + strlwr(user); + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + + // Generate a user ID. + userID = genUniqueId(user); + + SetKeyValue(path, "Password", password); + SetKeyInt(path, "Flags", 0); + SetKeyValue(path, "Home", "/boot/home"); + SetKeyValue(path, "Group", "everyone"); + SetKeyInt(path, "UID", userID); + +// fs_write_attr(file, "BEOS:TYPE", B_STRING_TYPE, 0, BT_MIME_USER, strlen(BT_MIME_USER)); + + // Add the user to the everyone group. + addUserToGroup(user, "everyone"); + return true; +} + +bool createGroup(char *group) +{ + char path[B_PATH_NAME_LENGTH]; + uint32 groupID; + + // All usernames are saved in lowercase. + strlwr(group); + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/groups/"); + strcat(path, group); + + // Generate a group ID. + groupID = genUniqueId(group); + + if (mkdir(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1) + return false; + + strcat(path, "/.attrib"); + SetKeyInt(path, "GID", groupID); +// fs_write_attr(file, "BEOS:TYPE", B_STRING_TYPE, 0, BT_MIME_GROUP, strlen(BT_MIME_GROUP)); + return true; +} + +bool removeUser(char *user) +{ + DIR *dir; + struct dirent *dirInfo; + char path[B_PATH_NAME_LENGTH], groupPath[B_PATH_NAME_LENGTH]; + + // All usernames are saved in lowercase. + strlwr(user); + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + + // Remove the user file. + remove(path); + + // Now remove all instances of this user from any groups to which + // it belonged. + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/groups"); + + // Scan the list of groups. For each group, use removeFiles() to remove + // the user file from the that directory. + dir = opendir(path); + if (dir) + { + while ((dirInfo = readdir(dir)) != NULL) + if (strcmp(dirInfo->d_name, ".") && strcmp(dirInfo->d_name, "..")) + { + sprintf(groupPath, "%s/%s", path, dirInfo->d_name); + removeFiles(groupPath, user); + } + + closedir(dir); + } + + return true; +} + +bool removeGroup(char *group) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/groups/"); + strcat(path, group); + strlwr(path); + + removeFiles(path, NULL); + remove(path); + + return true; +} + +bool setUserFullName(char *user, char *fullName) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return SetKeyValue(path, "FullName", fullName); +} + +bool setUserDesc(char *user, char *desc) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return SetKeyValue(path, "Description", desc); +} + +bool setUserPassword(char *user, char *password) +{ + char path[B_PATH_NAME_LENGTH], code[35]; + + // Encrypt the password using MD5. + md5EncodeString(password, code); + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return SetKeyValue(path, "Password", code); +} + +bool setUserFlags(char *user, uint32 flags) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return SetKeyInt(path, "Flags", flags); +} + +bool setUserDaysToExpire(char *user, uint32 days) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return SetKeyInt(path, "DaysToExpire", days); +} + +bool setUserHome(char *user, char *home) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return SetKeyValue(path, "Home", home); +} + +bool setUserGroup(char *user, char *group) +{ + char path[B_PATH_NAME_LENGTH]; + + if (!addUserToGroup(user, group)) + return false; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return SetKeyValue(path, "Group", group); +} + +bool setGroupDesc(char *group, char *desc) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/groups/"); + strcat(path, group); + strcat(path, "/.attrib"); + strlwr(path); + + return SetKeyValue(path, "Description", desc); +} + +bool getUserFullName(char *user, char *fullName, int bufSize) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return GetKeyValue(path, "FullName", fullName, bufSize); +} + +bool getUserDesc(char *user, char *desc, int bufSize) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return GetKeyValue(path, "Description", desc, bufSize); +} + +bool getUserPassword(char *user, char *password, int bufSize) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return GetKeyValue(path, "Password", password, bufSize); +} + +bool getUserFlags(char *user, uint32 *flags) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return GetKeyInt(path, "Flags", (int *) &flags); +} + +bool getUserDaysToExpire(char *user, uint32 *days) +{ + char path[B_PATH_NAME_LENGTH]; + + days = 0; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return GetKeyInt(path, "DaysToExpire", (int *) &days); +} + +bool getUserHome(char *user, char *home, int bufSize) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return GetKeyValue(path, "Home", home, bufSize); +} + +bool getUserGroup(char *user, char *group, int bufSize) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users/"); + strcat(path, user); + strlwr(path); + + return GetKeyValue(path, "Group", group, bufSize); +} + +bool getGroupDesc(char *group, char *desc, int bufSize) +{ + char path[B_PATH_NAME_LENGTH]; + + // All usernames are saved in lowercase. + strlwr(group); + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/groups/"); + strcat(path, group); + strcat(path, "/.attrib"); + + return GetKeyValue(path, "Description", desc, bufSize); +} + +// strlwr() +// +static void strlwr(char *str) +{ + char *p; + for (p = str; *p; p++) + *p = tolower(*p); +} + +// genUniqueId() +// +// This function generates a unique number based upon a string. Currently, +// is uses the upper-most byte of a 4-byte integer to contain the length. +// This restricts the length of the supplied string to 256 characters. Then, +// the sum of each character multiplied by its position in the string is +// calculated and occupies the remaining 3 bytes. +// +static uint32 genUniqueId(char *str) +{ + char *p; + int i; + uint32 value = 0; + + for (p = str, i = 0; *p; p++, i++) + value += i * (int) *p; + + value = value | (i << 24); + return value; +} + +static void removeFiles(char *folder, char *file) +{ + DIR *dir; + struct dirent *dirInfo; + char path[B_PATH_NAME_LENGTH]; + + // If we've only been given one file, then just delete it. + if (file) + { + sprintf(path, "%s/%s", folder, file); + remove(path); + return; + } + + // Otherwise, we need to query all files in the directory and + // remove them. + dir = opendir(folder); + if (dir) + { + while ((dirInfo = readdir(dir)) != NULL) + if (strcmp(dirInfo->d_name, ".") && strcmp(dirInfo->d_name, "..")) + { + sprintf(path, "%s/%s", folder, dirInfo->d_name); + remove(path); + } + + closedir(dir); + } +} + +// OpenUsers() +// +DIR *OpenUsers() +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/users"); + + return opendir(path); +} + +// ReadUser() +// +dirent_t *ReadUser(DIR *dir) +{ + struct dirent *dirInfo; + + if (dir) + { + while ((dirInfo = readdir(dir)) != NULL) + if (dirInfo->d_name[0] != '.') + return dirInfo; + } + + return NULL; +} + +// CloseUsers() +// +void CloseUsers(DIR *dir) +{ + if (dir) + closedir(dir); +} + +// OpenGroups() +// +DIR *OpenGroups() +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/groups"); + + return opendir(path); +} + +// ReadGroup() +// +dirent_t *ReadGroup(DIR *dir) +{ + struct dirent *dirInfo; + + if (dir) + { + while ((dirInfo = readdir(dir)) != NULL) + if (dirInfo->d_name[0] != '.') + return dirInfo; + } + + return NULL; +} + +// CloseGroups() +// +void CloseGroups(DIR *dir) +{ + if (dir) + closedir(dir); +} + +// OpenGroup() +// +DIR *OpenGroup(char *group) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/groups/"); + strcat(path, group); + + return opendir(path); +} + +// ReadGroupMember() +// +dirent_t *ReadGroupMember(DIR *dir) +{ + struct dirent *dirInfo; + + if (dir) + { + while ((dirInfo = readdir(dir)) != NULL) + if (dirInfo->d_name[0] != '.') + return dirInfo; + } + + return NULL; +} + +// CloseGroup() +// +void CloseGroup(DIR *dir) +{ + if (dir) + closedir(dir); +} + +// isServerRecordingLogins() +// +bool isServerRecordingLogins(char *server) +{ + char path[B_PATH_NAME_LENGTH]; + char buffer[20]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/servers/"); + strcat(path, server); + strlwr(path); + + GetKeyValue(path, "RecordLogins", buffer, sizeof(buffer)); + return strcasecmp(buffer, "Yes") == 0; +} + +// setServerRecordingLogins() +// +bool setServerRecordingLogins(char *server, bool recording) +{ + char path[B_PATH_NAME_LENGTH]; + + find_directory(B_COMMON_SYSTEM_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/domains/default/servers/"); + strcat(path, server); + strlwr(path); + + return SetKeyValue(path, "RecordLogins", recording ? "Yes" : "No"); +} + +// MakeServerKey() +// +void MakeServerKey(char *server, char *key) +{ + struct hostent *ent; + char str[256]; + + srand(time(NULL)); + sprintf(str, "%s-%x-", server, rand() * 0xFFFFFFFF); + ent = gethostbyname(server); + strcat(str, ent ? ent->h_name : "Unknown"); + + md5EncodeString(str, key); +} + +// GetServerList() +// +int GetServerList(recordServerFunc recServ) +{ + thread_id queryThread = spawn_thread(queryServers, "Server Query", B_NORMAL_PRIORITY, recServ); + resume_thread(queryThread); + return 0; +} + +int32 queryServers(void *data) +{ + bt_request request; + recordServerFunc recServ = (recordServerFunc) data; + struct sockaddr_in ourAddr, toAddr, fromAddr; + struct hostent *ent; + char response[256], hostname[B_FILE_NAME_LENGTH]; + int sock, addrLen, bytes; +#ifdef SO_BROADCAST + int on = 1; +#endif + + memset(&toAddr, 0, sizeof(toAddr)); + toAddr.sin_family = AF_INET; + toAddr.sin_port = htons(BT_QUERYHOST_PORT); + toAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); + + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock == INVALID_SOCKET) + return -1; + + memset(&ourAddr, 0, sizeof(ourAddr)); + ourAddr.sin_family = AF_INET; + ourAddr.sin_port = htons(BT_QUERYHOST_PORT); + ourAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(sock, (struct sockaddr *) &ourAddr, sizeof(ourAddr))) + if (errno != EADDRINUSE) + return -1; + + // Normally, a setsockopt() call is necessary to turn broadcast mode on + // explicitly, although some versions of Unix don't care. BeOS doesn't + // currently even define SO_BROADCAST, unless you have BONE installed. +#ifdef SO_BROADCAST + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) + { + closesocket(sock); + return -1; + } +#endif + signal(SIGALRM, recvAlarm); + + strcpy(request.signature, BT_RPC_SIGNATURE); + request.command = BT_REQ_HOST_PROBE; + if (sendto(sock, (char *) &request, sizeof(request), 0, (struct sockaddr *) &toAddr, sizeof(toAddr)) == -1) + { + closesocket(sock); + return -1; + } + + memset(response, 0, sizeof(response)); + alarm(3); + + while (1) + { + addrLen = sizeof(fromAddr); + bytes = recvfrom(sock, response, sizeof(response) - 1, 0, (struct sockaddr *) &fromAddr, &addrLen); + if (bytes < 0) + { + if (errno == EINTR) + break; + } + + if (strncmp(response, BT_RPC_SIGNATURE, strlen(BT_RPC_SIGNATURE)) != 0) + { + struct sockaddr_in *sin = (struct sockaddr_in *) &fromAddr; + ent = gethostbyaddr((char *) &sin->sin_addr, sizeof(sin->sin_addr), AF_INET); + if (ent) + (*recServ)(ent->h_name, *((uint32 *) &sin->sin_addr)); + else + { + uint8 *p = (uint8 *) &sin->sin_addr; + sprintf(hostname, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + (*recServ)(hostname, *((uint32 *) &sin->sin_addr)); + } + } + } + + alarm(0); + signal(SIGALRM, SIG_DFL); + closesocket(sock); + return 0; +} + +static void recvAlarm(int signal) +{ + return; +} + +// ----- Key-Value Implementation ------------------------------------------------ + +bool GetKeyInt(const char *fileName, const char *key, int *value) +{ + char num[50]; + + *value = 0; + if (GetKeyValue(fileName, key, num, sizeof(num))) + { + *value = atoi(num); + return true; + } + + return false; +} + +bool GetKeyValue(const char *fileName, const char *key, char *value, int bufSize) +{ + FILE *fp; + key_value *kv; + int length; + + value[0] = 0; + + fp = fopen(fileName, "r"); + if (!fp) + return false; + + while ((kv = GetNextKey(fp)) != NULL) + if (strcasecmp(kv->key, key) == 0) + { + length = min(bufSize - 1, kv->valLength); + strncpy(value, kv->value, length); + value[length] = 0; + FreeKeyValue(kv); + break; + } + else FreeKeyValue(kv); + + fclose(fp); + return (*value != 0); +} + +bool SetKeyInt(const char *fileName, const char *key, int value) +{ + char num[50]; + sprintf(num, "%d", value); + return SetKeyValue(fileName, key, num); +} + +bool SetKeyValue(const char *fileName, const char *key, const char *value) +{ + key_value *kv[100]; + FILE *fp; + int i, j, length; + bool found = false; + + i = 0; + found = false; + length = value ? strlen(value) : 0; + + fp = fopen(fileName, "r"); + if (fp) + { + while ((kv[i] = GetNextKey(fp)) != NULL) + { + if (strcasecmp(kv[i]->key, key) == 0) + { + found = true; + free(kv[i]->value); + kv[i]->value = (char *) malloc(strlen(value) + 1); + if (kv[i]->value) + if (length) + strcpy(kv[i]->value, value); + else + kv[i]->value[0] = 0; + + kv[i]->valLength = length; + } + + i++; + } + + fclose(fp); + } + + fp = fopen(fileName, "w"); + if (fp) + { + for (j = 0; j < i; j++) + if (kv[j] && kv[j]->value && kv[j]->valLength) + { + fprintf(fp, "%s = %s\n", kv[j]->key, kv[j]->value); + FreeKeyValue(kv[j]); + } + + if (!found && length) + fprintf(fp, "%s = %s\n", key, value); + + fclose(fp); + } + + return true; +} + +key_value *GetNextKey(FILE *fp) +{ + key_value *kv; + char buffer[4096], key[35], *ch; + int i, length; + + if (!fgets(buffer, sizeof(buffer), fp)) + return NULL; + + // The minimum length for a valid line is one character for the key, plus the + // equal sign, plus one character for the value, or 3 characters. + length = strlen(buffer); + if (length < 3) + return NULL; + + // Trim off any linefeed character. + if (buffer[length - 1] == '\n') + buffer[--length] = 0; + + // Now skip spaces before the key. + ch = buffer; + while (*ch && (*ch == ' ' || *ch == '\t')) + ch++; + + for (i = 0; *ch && *ch != ' ' && *ch != '\t' && *ch != '='; i++, ch++) + if (i < sizeof(key) - 1) + key[i] = *ch; + + key[i] = 0; + if (i == 0) + return NULL; + + kv = (key_value *) malloc(sizeof(key_value)); + if (!kv) + return NULL; + + kv->key = (char *) malloc(i + 1); + if (!kv->key) + { + free(kv); + return NULL; + } + + strcpy(kv->key, key); + + // Skip to the equal sign. + while (*ch && *ch != '=') + ch++; + + if (*ch != '=') + { + free(kv->key); + free(kv); + return NULL; + } + + ch++; + while (*ch && (*ch == ' ' || *ch == '\t')) + ch++; + + kv->valLength = buffer + length - ch; + kv->value = (char *) malloc(kv->valLength + 1); + if (!kv->value) + { + free(kv->key); + free(kv); + return NULL; + } + + strcpy(kv->value, ch); + return kv; +} + +void FreeKeyValue(key_value *kv) +{ + if (kv->key) + free(kv->key); + + if (kv->value) + free(kv->value); + + free(kv); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/besure_auth.h b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/besure_auth.h new file mode 100644 index 0000000000..0a3a551871 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/besure_auth.h @@ -0,0 +1,75 @@ +#ifndef _BESURE_AUTH_H_ +#define _BESURE_AUTH_H_ + +#include + +#define USER_FLAG_DISABLED 0x00000001 +#define USER_FLAG_INIT_EXPIRE 0x00000002 +#define USER_FLAG_DAYS_EXPIRE 0x00000004 +#define USER_FLAG_PW_LOCKED 0x00000008 + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +typedef void (*recordServerFunc)(char *name, uint32 addr); + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE bool createUser(char *user, char *password); +_IMPEXP_BESURE bool createGroup(char *group); +_IMPEXP_BESURE bool removeUser(char *user); +_IMPEXP_BESURE bool removeGroup(char *group); +_IMPEXP_BESURE bool addUserToGroup(char *user, char *group); +_IMPEXP_BESURE bool removeUserFromGroup(char *user, char *group); +_IMPEXP_BESURE bool isUserInGroup(char *user, char *group); + +_IMPEXP_BESURE bool setUserFullName(char *user, char *fullName); +_IMPEXP_BESURE bool setUserDesc(char *user, char *desc); +_IMPEXP_BESURE bool setUserPassword(char *user, char *password); +_IMPEXP_BESURE bool setUserFlags(char *user, uint32 flags); +_IMPEXP_BESURE bool setUserDaysToExpire(char *user, uint32 days); +_IMPEXP_BESURE bool setUserHome(char *user, char *home); +_IMPEXP_BESURE bool setUserGroup(char *user, char *group); +_IMPEXP_BESURE bool setGroupDesc(char *group, char *desc); + +_IMPEXP_BESURE bool getUserFullName(char *user, char *fullName, int bufSize); +_IMPEXP_BESURE bool getUserDesc(char *user, char *desc, int bufSize); +_IMPEXP_BESURE bool getUserPassword(char *user, char *password, int bufSize); +_IMPEXP_BESURE bool getUserFlags(char *user, uint32 *flags); +_IMPEXP_BESURE bool getUserDaysToExpire(char *user, uint32 *days); +_IMPEXP_BESURE bool getUserHome(char *user, char *home, int bufSize); +_IMPEXP_BESURE bool getUserGroup(char *user, char *group, int bufSize); +_IMPEXP_BESURE bool getGroupDesc(char *group, char *desc, int bufSize); + +_IMPEXP_BESURE bool isServerRecordingLogins(char *server); +_IMPEXP_BESURE bool setServerRecordingLogins(char *server, bool recording); + +_IMPEXP_BESURE void MakeServerKey(char *server, char *key); + +_IMPEXP_BESURE DIR *OpenUsers(); +_IMPEXP_BESURE dirent_t *ReadUser(DIR *dir); +_IMPEXP_BESURE void CloseUsers(DIR *dir); +_IMPEXP_BESURE DIR *OpenGroups(); +_IMPEXP_BESURE dirent_t *ReadGroup(DIR *dir); +_IMPEXP_BESURE void CloseGroups(DIR *dir); +_IMPEXP_BESURE DIR *OpenGroup(char *group); +_IMPEXP_BESURE dirent_t *ReadGroupMember(DIR *dir); +_IMPEXP_BESURE void CloseGroup(DIR *dir); +_IMPEXP_BESURE int GetServerList(recordServerFunc recServ); + +_IMPEXP_BESURE bool GetKeyValue(const char *fileName, const char *key, char *value, int bufSize); +_IMPEXP_BESURE bool GetKeyInt(const char *fileName, const char *key, int *value); +_IMPEXP_BESURE bool SetKeyValue(const char *fileName, const char *key, const char *value); +_IMPEXP_BESURE bool SetKeyInt(const char *fileName, const char *key, int value); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/betalk.h new file mode 100644 index 0000000000..af38d0d926 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +// The different types of network resources supported by BeServed. +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRITNER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 32768 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 128 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int nsid; + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +typedef struct rpcInfo +{ + thread_id rpcThread; + int32 quitXID; + + uint32 serverIP; + int32 serverPort; + int s; +} bt_rpcinfo; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket inPacket; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/md5.c b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/md5.c new file mode 100644 index 0000000000..92f51d890b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/md5.c @@ -0,0 +1,408 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id: md5.c $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include "stdio.h" +#include "md5.h" + +#ifdef TEST +/* + * Compile with -DTEST to create a self-contained executable test program. + * The test program should print out the same values as given in section + * A.5 of RFC 1321, reproduced below. + */ +#include +main() +{ + static const char *const test[7] = { + "", /*d41d8cd98f00b204e9800998ecf8427e*/ + "a", /*0cc175b9c0f1b6a831c399e269772661*/ + "abc", /*900150983cd24fb0d6963f7d28e17f72*/ + "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/ + "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + /*d174ab98d277d9f5a5611c2c9f419d9f*/ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/ + }; + int i; + + for (i = 0; i < 7; ++i) { + md5_state_t state; + md5_byte_t digest[16]; + int di; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); + md5_finish(&state, digest); + printf("MD5 (\"%s\") = ", test[i]); + for (di = 0; di < 16; ++di) + printf("%02x", digest[di]); + printf("\n"); + } + return 0; +} +#endif /* TEST */ + + +/* + * For reference, here is the program that computed the T values. + */ +#if 0 +#include +main() +{ + int i; + for (i = 1; i <= 64; ++i) { + unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); + printf("#define T%d 0x%08lx\n", i, v); + } + return 0; +} +#endif + +void md5EncodeString(const char *source, char *dest) +{ + md5_state_t state; + md5_byte_t digest[16]; + int i; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *) source, strlen(source)); + md5_finish(&state, digest); + + for (i = 0; i < 16; i++) + sprintf(dest + (i * 2), "%02x", digest[i]); +} + +/* + * End of T computation program. + */ +#define T1 0xd76aa478 +#define T2 0xe8c7b756 +#define T3 0x242070db +#define T4 0xc1bdceee +#define T5 0xf57c0faf +#define T6 0x4787c62a +#define T7 0xa8304613 +#define T8 0xfd469501 +#define T9 0x698098d8 +#define T10 0x8b44f7af +#define T11 0xffff5bb1 +#define T12 0x895cd7be +#define T13 0x6b901122 +#define T14 0xfd987193 +#define T15 0xa679438e +#define T16 0x49b40821 +#define T17 0xf61e2562 +#define T18 0xc040b340 +#define T19 0x265e5a51 +#define T20 0xe9b6c7aa +#define T21 0xd62f105d +#define T22 0x02441453 +#define T23 0xd8a1e681 +#define T24 0xe7d3fbc8 +#define T25 0x21e1cde6 +#define T26 0xc33707d6 +#define T27 0xf4d50d87 +#define T28 0x455a14ed +#define T29 0xa9e3e905 +#define T30 0xfcefa3f8 +#define T31 0x676f02d9 +#define T32 0x8d2a4c8a +#define T33 0xfffa3942 +#define T34 0x8771f681 +#define T35 0x6d9d6122 +#define T36 0xfde5380c +#define T37 0xa4beea44 +#define T38 0x4bdecfa9 +#define T39 0xf6bb4b60 +#define T40 0xbebfbc70 +#define T41 0x289b7ec6 +#define T42 0xeaa127fa +#define T43 0xd4ef3085 +#define T44 0x04881d05 +#define T45 0xd9d4d039 +#define T46 0xe6db99e5 +#define T47 0x1fa27cf8 +#define T48 0xc4ac5665 +#define T49 0xf4292244 +#define T50 0x432aff97 +#define T51 0xab9423a7 +#define T52 0xfc93a039 +#define T53 0x655b59c3 +#define T54 0x8f0ccc92 +#define T55 0xffeff47d +#define T56 0x85845dd1 +#define T57 0x6fa87e4f +#define T58 0xfe2ce6e0 +#define T59 0xa3014314 +#define T60 0x4e0811a1 +#define T61 0xf7537e82 +#define T62 0xbd3af235 +#define T63 0x2ad7d2bb +#define T64 0xeb86d391 + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; + +#ifndef ARCH_IS_BIG_ENDIAN +# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ +#endif +#if ARCH_IS_BIG_ENDIAN + + /* + * On big-endian machines, we must arrange the bytes in the right + * order. (This also works on machines of unknown byte order.) + */ + md5_word_t X[16]; + const md5_byte_t *xp = data; + int i; + + for (i = 0; i < 16; ++i, xp += 4) + X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + +#else /* !ARCH_IS_BIG_ENDIAN */ + + /* + * On little-endian machines, we can process properly aligned data + * without copying it. + */ + md5_word_t xbuf[16]; + const md5_word_t *X; + + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } +#endif + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = 0xefcdab89; + pms->abcd[2] = 0x98badcfe; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/md5.h b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/md5.h new file mode 100644 index 0000000000..4148570cd7 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/md5.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id: md5.h $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This code has some adaptations for the Ghostscript environment, but it + * will compile and run correctly in any environment with 8-bit chars and + * 32-bit ints. Specifically, it assumes that if the following are + * defined, they have the same meaning as in Ghostscript: P1, P2, P3, + * ARCH_IS_BIG_ENDIAN. + */ + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE void md5EncodeString(const char *source, char *dest); + +/* Initialize the algorithm. */ +#ifdef P1 +void md5_init(P1(md5_state_t *pms)); +#else +void md5_init(md5_state_t *pms); +#endif + +/* Append a string to the message. */ +#ifdef P3 +void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); +#else +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +#endif + +/* Finish the message and return the digest. */ +#ifdef P2 +void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); +#else +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/sysdepdefs.h b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/sysdepdefs.h new file mode 100644 index 0000000000..6bb4bd5051 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/AuthLib/sysdepdefs.h @@ -0,0 +1,10 @@ +#ifndef _SYSDEPDEFS_H_ +#define _SYSDEPDEFS_H_ + +#ifdef BONE_VERSION + +#define closesocket(s) close(s) + +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/BeManager.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/BeManager.cpp new file mode 100644 index 0000000000..60d76f77fa --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/BeManager.cpp @@ -0,0 +1,246 @@ +#include +#include +#include +#include +#include +#include +#include "Mime.h" +#include "FindDirectory.h" + +#include +#include +#include +#include + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVListItem.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#include "ConsoleHeaderView.h" +#include "UserProperties.h" +#include "TreeControl.h" +#include "ListControl.h" +#include "Users.h" +#include "Groups.h" +#include "Servers.h" +#include "Icons.h" + +const int32 MSG_ITEM_SELECT = 'ISel'; +const int32 MSG_ITEM_INVOKE = 'IInv'; +const int32 MSG_LIST_DESELECT = 'CLV0'; + + +// ----- GenericWindow -------------------------------------------- + +class GenericWindow : public BWindow +{ + public: + GenericWindow() : + BWindow(BRect(40, 40, 630, 430), "Domain Management Console", B_DOCUMENT_WINDOW, 0) + { + BRect r = Bounds(); + r.bottom = 82; + headerView = new ConsoleHeaderView(r); + AddChild(headerView); + + r = Bounds(); + r.top = 85; + r.right = 160; + // r.bottom -= B_H_SCROLL_BAR_HEIGHT; + + CLVContainerView *treeContView, *listContView; + + treeView = new SmartTreeListView(r, &treeContView, NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST, + true, true, true, false, B_FANCY_BORDER); + treeView->AddColumn(new CLVColumn(NULL, 20.0, CLV_EXPANDER | CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE, 20.0)); + treeView->AddColumn(new CLVColumn(NULL, 16.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT, 16.0)); + treeView->AddColumn(new CLVColumn("Snap-ins", 125.0, CLV_SORT_KEYABLE, 50.0)); + treeView->SetSortFunction(TreeItem::MyCompare); + + r = Bounds(); + r.top = 85; + r.left = 165 + B_V_SCROLL_BAR_WIDTH; + r.right -= B_V_SCROLL_BAR_WIDTH; + + listView = new SmartColumnListView(r, &listContView, NULL, B_FOLLOW_ALL_SIDES, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST, + false, true, true, false, B_FANCY_BORDER); + + listView->SetSelectionMessage(new BMessage(MSG_ITEM_SELECT)); + listView->SetInvocationMessage(new BMessage(MSG_ITEM_INVOKE)); + + AddTreeItems(treeView); + AddChild(treeContView); + AddChild(listContView); + + SetSizeLimits(300, 2000, 150, 2000); + Show(); + } + + ~GenericWindow() + { + be_app->PostMessage(B_QUIT_REQUESTED); + } + + // MessageReceived() + // + void MessageReceived(BMessage *msg) + { + TreeItem *treeItem = NULL; + ListItem *listItem = NULL; + int32 curTreeItem = treeView->CurrentSelection(); + int32 curListItem = listView->CurrentSelection(); + + if (curTreeItem >= 0) + treeItem = (TreeItem *) treeView->ItemAt(curTreeItem); + + if (curListItem >= 0) + listItem = (ListItem *) listView->ItemAt(curListItem); + + switch (msg->what) + { + case MSG_ITEM_INVOKE: + if (listItem) + if (listItem->ItemInvoked()) + if (treeItem) + treeItem->ListItemUpdated(curListItem, listItem); + break; + + case MSG_ITEM_SELECT: + if (treeItem) + treeItem->ListItemSelected(); + if (listItem) + listItem->ItemSelected(); + break; + + case MSG_LIST_DESELECT: + if (treeItem) + treeItem->ListItemDeselected(); + if (listItem) + listItem->ItemDeselected(); + break; + + // If we get here, this may be a message we don't handle, or it may be one + // that comes from the header view and needs to be processed by the associated + // tree node. + default: + if (treeItem) + if (treeItem->HeaderMessageReceived(msg)) + break; + + BWindow::MessageReceived(msg); + break; + } + } + + void Quit() + { + TreeItem *item; + + do + { + item = (TreeItem *) treeView->RemoveItem(int32(0)); + if (item) + delete item; + } while(item); + + BWindow::Quit(); + } + + private: + void AddTreeItems(ColumnListView* treeView) + { + treeView->AddItem(new TreeItem(0, true, true, ICON_NETADMIN_SMALL, headerView, listView, "Network Administration")); + treeView->AddItem(new TreeItem(1, true, true, ICON_DOMAIN_SMALL, headerView, listView, "Domains")); + treeView->AddItem(new TreeItem(2, true, true, ICON_DOMAIN_SMALL, headerView, listView, "default")); + treeView->AddItem(new GroupsItem(3, false, false, ICON_GROUP_SMALL, headerView, listView, "Groups")); + treeView->AddItem(new ServersItem(3, false, false, ICON_HOST_SMALL, headerView, listView, "Servers")); + treeView->AddItem(new UsersItem(3, false, false, ICON_USER_SMALL, headerView, listView, "Users")); + treeView->AddItem(new TreeItem(1, false, false, ICON_SERVICES_SMALL, headerView, listView, "Services")); + } + + ConsoleHeaderView *headerView; + SmartTreeListView *treeView; + SmartColumnListView *listView; +}; + + +// ----- GenericApp --------------------------------------------------- + +class GenericApp : public BApplication +{ + public: + GenericApp() : BApplication("application/x-vnd.Teldar-DomainManager") + { + checkMimeTypes(); + new GenericWindow; + } + + ~GenericApp() + { + } + + private: + void checkMimeTypes() + { + BMimeType mime; + mime.SetTo("application/x-vnd.BeServed-DomainManager"); + if (!mime.IsInstalled()) + { + mime.Install(); + mime.SetShortDescription("DomainManager"); + mime.SetLongDescription("BeServed Domain Management Console 1.2.6"); + setMimeIcon(&mime, ICON_BMC_LARGE, B_LARGE_ICON); + setMimeIcon(&mime, ICON_BMC_SMALL, B_MINI_ICON); + } + + mime.SetTo("application/x-vnd.Teldar-User"); + if (!mime.IsInstalled()) + { + mime.Install(); + mime.SetShortDescription("User"); + mime.SetLongDescription("BeSure User Account"); + setMimeIcon(&mime, ICON_USER_LARGE, B_LARGE_ICON); + setMimeIcon(&mime, ICON_USER_SMALL, B_MINI_ICON); + } + + mime.SetTo("application/x-vnd.Teldar-Group"); + if (!mime.IsInstalled()) + { + mime.Install(); + mime.SetShortDescription("User Group"); + mime.SetLongDescription("BeSure Group Account"); + setMimeIcon(&mime, ICON_GROUP_LARGE, B_LARGE_ICON); + setMimeIcon(&mime, ICON_GROUP_SMALL, B_MINI_ICON); + } + } + + bool setMimeIcon(BMimeType *mime, int32 resourceID, icon_size which) + { + BMessage archive; + size_t size; + char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), resourceID, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + { + BBitmap *icon = new BBitmap(&archive); + mime->SetIcon(icon, which); + return true; + } + + return false; + } +}; + +#include "besure_auth.h" + +int main() +{ + new GenericApp; + be_app->Run(); + delete be_app; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/BeManager.proj b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/BeManager.proj new file mode 100644 index 0000000000..cfab435413 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/BeManager.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/BeManager_Bone.proj b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/BeManager_Bone.proj new file mode 100644 index 0000000000..da69003c4b Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/BeManager_Bone.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ConsoleHeaderView.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ConsoleHeaderView.cpp new file mode 100644 index 0000000000..051cc98107 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ConsoleHeaderView.cpp @@ -0,0 +1,60 @@ +#include "View.h" +#include "Mime.h" +#include "TypeConstants.h" +#include "Application.h" +#include "InterfaceDefs.h" +#include "Bitmap.h" +#include "TranslationUtils.h" +#include "Alert.h" +#include "Button.h" +#include "Errors.h" + +#include "ConsoleHeaderView.h" + +// ----- ConsoleHeaderView --------------------------------------------------------------- + +ConsoleHeaderView::ConsoleHeaderView(BRect rect) + : BView(rect, "ConsoleHeaderView", B_FOLLOW_TOP | B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW) +{ + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.BeServed-DomainManager"); + mime.GetIcon(icon, B_LARGE_ICON); +} + +ConsoleHeaderView::~ConsoleHeaderView() +{ +} + +void ConsoleHeaderView::Draw(BRect rect) +{ + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + DrawString("BeServed Domain Management Console"); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("Version 1.2.6"); + MovePenTo(55, 40); + DrawString(""); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ConsoleHeaderView.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ConsoleHeaderView.h new file mode 100644 index 0000000000..6beee6f115 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ConsoleHeaderView.h @@ -0,0 +1,14 @@ +class ConsoleHeaderView : public BView +{ + public: + ConsoleHeaderView(BRect rect); + ~ConsoleHeaderView(); + + void Draw(BRect rect); + + BButton *openBtn; + BButton *hostBtn; + + private: + BBitmap *icon; +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Explorer.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Explorer.cpp new file mode 100644 index 0000000000..1a45bd092a --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Explorer.cpp @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include +#include "Mime.h" + +#include "string.h" +#include "stdio.h" +#include "dirent.h" +#include "sys/stat.h" + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVListItem.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#include "TreeControl.h" +#include "ListControl.h" +#include "Explorer.h" +#include "Icons.h" + + +ExplorerFile::ExplorerFile(BView *headerView, const char *text0, const char *text1, const char *text2) : + ListItem(headerView, text0, text1, text2) +{ + BBitmap *icon; + BMessage archive; + size_t size; + + char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), 101, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + { + icon = new BBitmap(&archive); + + SetColumnContent(0, icon, 2.0); + SetColumnContent(1, text0); + SetColumnContent(2, text1); + SetColumnContent(3, text2); + } +} + +ExplorerFile::~ExplorerFile() +{ +} + +bool ExplorerFile::ItemInvoked() +{ + return false; +} + + + +ExplorerFolder::ExplorerFolder(uint32 level, bool superitem, bool expanded, int32 resourceID, BView *headerView, ColumnListView *treeView, ColumnListView *listView, char *text) : + TreeItem(level, superitem, expanded, resourceID, headerView, listView, text) +{ + parentTreeView = treeView; +} + +void ExplorerFolder::ItemExpanding() +{ + DIR *dir; + struct dirent *dirInfo; + struct stat st; + char path[B_PATH_NAME_LENGTH], qualifiedFile[B_PATH_NAME_LENGTH]; + + ColumnListView *listView = GetAssociatedList(); + BView *headerView = GetAssociatedHeader(); + + strcpy(path, "/boot/home"); + dir = opendir(path); + if (dir) + { + while ((dirInfo = readdir(dir)) != NULL) + if (strcmp(dirInfo->d_name, ".") && strcmp(dirInfo->d_name, "..")) + { + sprintf(qualifiedFile, "%s/%s", path, dirInfo->d_name); + if (stat(qualifiedFile, &st) == 0) + if (S_ISDIR(st.st_mode)) + { + BAlert *alert = new BAlert("hello", dirInfo->d_name, "OK"); + alert->Go(); + parentTreeView->AddItem(new ExplorerFolder(OutlineLevel() + 1, true, false, ICON_HOST_SMALL, headerView, parentTreeView, listView, dirInfo->d_name)); + } + } + + closedir(dir); + } +} + +void ExplorerFolder::ItemSelected() +{ + DIR *dir; + struct dirent *dirInfo; + struct stat st; + char path[B_PATH_NAME_LENGTH], qualifiedFile[B_PATH_NAME_LENGTH]; + + PurgeRows(); + PurgeColumns(); + + ColumnListView *listView = GetAssociatedList(); + BView *headerView = GetAssociatedHeader(); + + listView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT)); + listView->AddColumn(new CLVColumn("File", 85.0, CLV_SORT_KEYABLE, 50.0)); + listView->AddColumn(new CLVColumn("Size", 130.0, CLV_SORT_KEYABLE)); + listView->AddColumn(new CLVColumn("Date", 150.0, CLV_SORT_KEYABLE)); + + strcpy(path, "/boot/home"); + dir = opendir(path); + if (dir) + { + while ((dirInfo = readdir(dir)) != NULL) + if (strcmp(dirInfo->d_name, ".") && strcmp(dirInfo->d_name, "..")) + { + sprintf(qualifiedFile, "%s/%s", path, dirInfo->d_name); + if (stat(qualifiedFile, &st) == 0) + if (!S_ISDIR(st.st_mode)) + listView->AddItem(new ExplorerFile(headerView, dirInfo->d_name, "", "")); + } + + closedir(dir); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Explorer.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Explorer.h new file mode 100644 index 0000000000..e8aae300de --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Explorer.h @@ -0,0 +1,25 @@ +// ----- ExplorerFile ---------------------------------------------------------------------- + +class ExplorerFile : public ListItem +{ + public: + ExplorerFile(BView *headerView, const char *text0, const char *text1, const char *text2); + virtual ~ExplorerFile(); + + bool ItemInvoked(); +}; + + +// ----- ExplorerFolder ----------------------------------------------------- + +class ExplorerFolder : public TreeItem +{ + public: + ExplorerFolder(uint32 level, bool superitem, bool expanded, int32 resourceID, BView *headerView, ColumnListView *treeView, ColumnListView *listView, char *text); + + void ItemExpanding(); + void ItemSelected(); + + private: + ColumnListView *parentTreeView; +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/GroupProperties.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/GroupProperties.cpp new file mode 100644 index 0000000000..d1ba6dcf21 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/GroupProperties.cpp @@ -0,0 +1,344 @@ +#include "Application.h" +#include "Resources.h" +#include "Window.h" +#include "View.h" +#include "Region.h" +#include "Button.h" +#include "CheckBox.h" +#include "TextControl.h" +#include "Bitmap.h" +#include "Mime.h" +#include "FilePanel.h" +#include "Menu.h" +#include "PopUpMenu.h" +#include "MenuItem.h" +#include "MenuField.h" +#include "String.h" + +#include "dirent.h" + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVListItem.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#include "ListControl.h" +#include "PickUser.h" +#include "GroupProperties.h" +#include "Icons.h" +#include "besure_auth.h" + +const int32 MSG_GROUP_OK = 'GOky'; +const int32 MSG_GROUP_CANCEL = 'GCan'; +const int32 MSG_GROUP_REFRESH = 'GRef'; +const int32 MSG_GROUP_ADD = 'GAdd'; +const int32 MSG_GROUP_REMOVE = 'GRem'; +const int32 MSG_MEMBER_SELECT = 'MSel'; + + +// ----- MemberItem ------------------------------------------------------------ + +MemberItem::MemberItem(BView *headerView, const char *text0, const char *text1, const char *text2) : + ListItem(headerView, text0, text1, text2) +{ + BBitmap *icon; + BMessage archive; + size_t size; + + char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_USER_SMALL, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + { + icon = new BBitmap(&archive); + + SetAssociatedHeader(headerView); + SetColumnContent(0, icon, 2.0); + SetColumnContent(1, text0); + SetColumnContent(2, text1); + SetColumnContent(3, text2); + } +} + +MemberItem::~MemberItem() +{ +} + +void MemberItem::ItemSelected() +{ + GroupPropertiesView *view = (GroupPropertiesView *) GetAssociatedHeader(); + view->GetRemoveButton()->SetEnabled(true); +} + +void MemberItem::ItemDeselected() +{ + GroupPropertiesView *view = (GroupPropertiesView *) GetAssociatedHeader(); + view->GetRemoveButton()->SetEnabled(false); +} + +// ----- GroupPropertiesView ----------------------------------------------------- + +GroupPropertiesView::GroupPropertiesView(BRect rect, const char *name) : + BView(rect, "GroupInfoView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + newGroup = name == NULL; + strcpy(group, newGroup ? "unknown" : name); + getGroupDesc(group, desc, sizeof(desc)); + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.Teldar-Group"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r(10, 52, 200, 72); + editName = new BTextControl(r, "GroupName", "Name:", group, NULL); + editName->SetDivider(70); + editName->SetEnabled(newGroup); + AddChild(editName); + + r.Set(10, 77, 250, 97); + editDesc = new BTextControl(r, "Description", "Description:", desc, NULL); + editDesc->SetDivider(70); + AddChild(editDesc); + + r.Set(205, 320, 275, 340); + BButton *okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_GROUP_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(285, 320, 360, 340); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_GROUP_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); + + r.Set(285, 125, 360, 145); + AddChild(new BButton(r, "AddUserBtn", "Add", new BMessage(MSG_GROUP_ADD), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); + + r.Set(285, 155, 360, 175); + removeBtn = new BButton(r, "RemoveBtn", "Remove", new BMessage(MSG_GROUP_REMOVE), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + removeBtn->SetEnabled(false); + AddChild(removeBtn); + + // Now add the membership list. + CLVContainerView *listContView; + r.Set(13, 125, 280 - B_V_SCROLL_BAR_WIDTH, 305); + listView = new SmartColumnListView(r, &listContView, NULL, B_FOLLOW_ALL_SIDES, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST, + false, false, true, false, B_FANCY_BORDER); + + listView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT)); + listView->AddColumn(new CLVColumn("User", 85.0, CLV_SORT_KEYABLE, 50.0)); + listView->AddColumn(new CLVColumn("Full Name", 130.0, CLV_SORT_KEYABLE)); + + listView->SetSelectionMessage(new BMessage(MSG_MEMBER_SELECT)); + listView->SetInvocationMessage(new BMessage(MSG_LIST_DESELECT)); + + AddGroupMembers(listView); + AddChild(listContView); +} + +GroupPropertiesView::~GroupPropertiesView() +{ +} + +void GroupPropertiesView::Draw(BRect rect) +{ + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + BString string(group); + string += " Properties"; + DrawString(string.String()); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("Groups are collections of users that will share certain properties,"); + MovePenTo(55, 40); + DrawString("such as access to files or network resources."); + + MovePenTo(13, 121); + DrawString("Current Members:"); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); +} + +void GroupPropertiesView::UpdateInfo() +{ + if (newGroup) + strcpy(group, editName->Text()); + + strcpy(desc, editDesc->Text()); +} + +void GroupPropertiesView::AddGroupMembers(ColumnListView* listView) +{ + DIR *groupList; + struct dirent *member; + + groupList = OpenGroup(group); + if (groupList) + { + while ((member = ReadGroupMember(groupList)) != NULL) + { + char desc[64]; + getUserFullName(member->d_name, desc, sizeof(desc)); + listView->AddItem(new MemberItem(this, member->d_name, desc, "")); + } + + CloseGroup(groupList); + } +} + +char *GroupPropertiesView::GetSelectedMember() +{ + if (listView) + { + int index = listView->CurrentSelection(); + if (index >= 0) + { + MemberItem *item = (MemberItem *) listView->ItemAt(index); + return ((char *) item->GetColumnContentText(1)); + } + } + + return NULL; +} + +void GroupPropertiesView::ItemSelected() +{ + removeBtn->SetEnabled(true); +} + +void GroupPropertiesView::ItemDeselected() +{ + removeBtn->SetEnabled(false); +} + +void GroupPropertiesView::AddNewMember(char *user) +{ + char desc[64]; + + addUserToGroup(user, group); + getUserFullName(user, desc, sizeof(desc)); + + listView->LockLooper(); + listView->AddItem(new MemberItem(this, user, desc, "")); + listView->UnlockLooper(); +} + +void GroupPropertiesView::RemoveSelectedMember() +{ + int index = listView->CurrentSelection(); + if (index >= 0) + { + MemberItem *item = (MemberItem *) listView->ItemAt(index); + if (item) + { + removeUserFromGroup((char *) item->GetColumnContentText(1), group); + + listView->LockLooper(); + listView->RemoveItem(item); + listView->UnlockLooper(); + } + } +} + + +// ----- GroupPropertiesPanel ---------------------------------------------------------------------- + +GroupPropertiesPanel::GroupPropertiesPanel(BRect frame, const char *name, BWindow *parent) : + BWindow(frame, name, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) +{ + newGroup = name == NULL; + if (!newGroup) + strcpy(group, name); + + shareWin = parent; + cancelled = true; + + BRect r = Bounds(); + infoView = new GroupPropertiesView(r, name == NULL ? NULL : group); + AddChild(infoView); + + Show(); +} + +// MessageReceived() +// +void GroupPropertiesPanel::MessageReceived(BMessage *msg) +{ + PickUserPanel *picker; + BRect frame; + status_t result; + char *user; + + switch (msg->what) + { + case MSG_GROUP_OK: +// relay = new BMessage(MSG_GROUP_REFRESH); +// relay->AddInt32("share", share); +// shareWin->PostMessage(relay); + cancelled = false; + infoView->UpdateInfo(); + if (newGroup) + { + strcpy(group, infoView->getGroup()); + createGroup(group); + } + + strcpy(desc, infoView->getDesc()); + setGroupDesc(group, desc); + BWindow::Quit(); + break; + + case MSG_GROUP_CANCEL: + cancelled = true; + BWindow::Quit(); + break; + + case MSG_MEMBER_SELECT: + infoView->ItemSelected(); + break; + + case (int32) 'CLV0': //MSG_LIST_DESELECT: + infoView->ItemDeselected(); + break; + + case MSG_GROUP_ADD: + frame = Frame(); + frame.left += 100; + frame.top += 25; + frame.right = frame.left + 285; + frame.bottom = frame.top + 340; + picker = new PickUserPanel(frame, group); + wait_for_thread(picker->Thread(), &result); + user = picker->GetUser(); + if (user) + infoView->AddNewMember(user); + break; + + case MSG_GROUP_REMOVE: + infoView->RemoveSelectedMember(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/GroupProperties.d b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/GroupProperties.d new file mode 100644 index 0000000000..1861d3a730 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/GroupProperties.d @@ -0,0 +1,32 @@ +GroupProperties.o : \ + /boot/home/BeServed/source/BeManager/GroupProperties.cpp \ + /boot/develop/headers/be/app/Application.h \ + /boot/develop/headers/be/storage/Resources.h \ + /boot/develop/headers/be/interface/Window.h \ + /boot/develop/headers/be/interface/View.h \ + /boot/develop/headers/be/interface/Region.h \ + /boot/develop/headers/be/interface/Button.h \ + /boot/develop/headers/be/interface/CheckBox.h \ + /boot/develop/headers/be/interface/TextControl.h \ + /boot/develop/headers/be/interface/Bitmap.h \ + /boot/develop/headers/be/storage/Mime.h \ + /boot/develop/headers/be/storage/FilePanel.h \ + /boot/develop/headers/be/interface/Menu.h \ + /boot/develop/headers/be/interface/PopUpMenu.h \ + /boot/develop/headers/be/interface/MenuItem.h \ + /boot/develop/headers/be/interface/MenuField.h \ + /boot/develop/headers/be/support/String.h \ + /boot/home/dev/Santas\ gift\ bag/ColumnListView/ColumnListView.h \ + /boot/home/dev/Santas\ gift\ bag/Colors.h \ + /boot/home/dev/Santas\ gift\ bag/ColumnListView/CLVColumn.h \ + /boot/home/dev/Santas\ gift\ bag/PrefilledBitmap/PrefilledBitmap.h \ + /boot/home/dev/Santas\ gift\ bag/BetterScrollView/BetterScrollView.h \ + /boot/home/dev/Santas\ gift\ bag/ScrollViewCorner/ScrollViewCorner.h \ + /boot/home/dev/Santas\ gift\ bag/ColumnListView/CLVListItem.h \ + /boot/home/dev/Santas\ gift\ bag/ColumnListView/CLVEasyItem.h \ + /boot/home/dev/Santas\ gift\ bag/NewStrings/NewStrings.h \ + /boot/home/BeServed/source/BeManager/ListControl.h \ + /boot/home/BeServed/source/BeManager/PickUser.h \ + /boot/home/BeServed/source/BeManager/GroupProperties.h \ + /boot/home/BeServed/source/BeManager/Icons.h \ + /boot/home/BeServed/source/BeManager/besure_auth.h diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/GroupProperties.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/GroupProperties.h new file mode 100644 index 0000000000..cc904fdef4 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/GroupProperties.h @@ -0,0 +1,64 @@ +// ----- MemberItem ---------------------------------------------------------------------- + +class MemberItem : public ListItem +{ + public: + MemberItem(BView *headerView, const char *text0, const char *text1, const char *text2); + ~MemberItem(); + + void ItemSelected(); + void ItemDeselected(); +}; + + +class GroupPropertiesView : public BView +{ + public: + GroupPropertiesView(BRect rect, const char *name); + ~GroupPropertiesView(); + + void Draw(BRect rect); + void UpdateInfo(); + char *GetSelectedMember(); + void ItemSelected(); + void ItemDeselected(); + void AddNewMember(char *user); + void RemoveSelectedMember(); + + BButton *GetRemoveButton() { return removeBtn; } + char *getGroup() { return group; } + char *getDesc() { return desc; } + + private: + void AddGroupMembers(ColumnListView* listView); + + BBitmap *icon; + BTextControl *editName; + BTextControl *editDesc; + SmartColumnListView *listView; + BButton *removeBtn; + + char group[33]; + char desc[64]; + bool newGroup; +}; + +class GroupPropertiesPanel : public BWindow +{ + public: + GroupPropertiesPanel(BRect frame, const char *name, BWindow *parent); + + void MessageReceived(BMessage *msg); + + char *getGroup() { return group; } + char *getDesc() { return desc; } + bool isCancelled() { return cancelled; } + + private: + GroupPropertiesView *infoView; + BWindow *shareWin; + char group[33]; + char desc[64]; + bool newGroup; + bool cancelled; +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Groups.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Groups.cpp new file mode 100644 index 0000000000..672bd2dab8 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Groups.cpp @@ -0,0 +1,222 @@ +#include "Application.h" +#include "Resources.h" +#include "Window.h" +#include "View.h" +#include "Region.h" +#include "Alert.h" +#include "Button.h" +#include "FindDirectory.h" +#include "Mime.h" + +#include "string.h" +#include "dirent.h" + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVListItem.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#include "TreeControl.h" +#include "ListControl.h" +#include "Groups.h" +#include "GroupProperties.h" +#include "Icons.h" +#include "besure_auth.h" + +#define WARN_REMOVE_GROUP "Removing this group may prevent access to network resources and may permanently relinquish any rights held by users not specifically granted access by user account or via membership in another group. Are you sure you want to remove this group?" + +const int32 MSG_GROUP_NEW = 'GNew'; +const int32 MSG_GROUP_EDIT = 'GEdt'; +const int32 MSG_GROUP_GONE = 'GGon'; + + +GroupItem::GroupItem(BView *headerView, ColumnListView *listView, const char *text0, const char *text1) : + ListItem(headerView, text0, text1, "") +{ + BBitmap *icon; + BMessage archive; + size_t size; + + list = listView; + + char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_GROUP_SMALL, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + { + icon = new BBitmap(&archive); + + SetColumnContent(0, icon, 2.0); + SetColumnContent(1, text0); + SetColumnContent(2, text1); + } +} + +GroupItem::~GroupItem() +{ +} + +bool GroupItem::ItemInvoked() +{ + BRect r; + BRect frame = GetAssociatedHeader()->Window()->Frame(); + status_t exitStatus; + + r.Set(frame.left + 150, frame.top + 25, frame.left + 520, frame.top + 375); // 370 x 350 + GroupPropertiesPanel *info = new GroupPropertiesPanel(r, GetColumnContentText(1), NULL); + wait_for_thread(info->Thread(), &exitStatus); + return (!info->isCancelled()); +} + +void GroupItem::ItemSelected() +{ +} + +void GroupItem::ItemDeselected() +{ +} + +void GroupItem::ItemDeleted() +{ + removeGroup((char *) GetColumnContentText(1)); +} + +bool GroupItem::IsDeleteable() +{ + BAlert *alert = new BAlert("Remove Group?", WARN_REMOVE_GROUP, "Yes", "No"); + alert->SetShortcut(1, B_ESCAPE); + alert->SetShortcut(0, 'y'); + alert->SetShortcut(1, 'n'); + return (alert->Go() == 0); +} + + +GroupsItem::GroupsItem(uint32 level, bool superitem, bool expanded, int32 resourceID, BView *headerView, ColumnListView *listView, char *text) : + TreeItem(level, superitem, expanded, resourceID, headerView, listView, text) +{ +} + +void GroupsItem::ItemSelected() +{ + DIR *dir; + struct dirent *dirInfo; + ColumnListView *listView; + BView *headerView; + + PurgeRows(); + PurgeColumns(); + PurgeHeader(); + BuildHeader(); + + listView = GetAssociatedList(); + headerView = GetAssociatedHeader(); + + listView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT)); + listView->AddColumn(new CLVColumn("Group", 85.0, CLV_SORT_KEYABLE, 50.0)); + listView->AddColumn(new CLVColumn("Description", 150.0, CLV_SORT_KEYABLE)); + + dir = OpenGroups(); + if (dir) + { + while ((dirInfo = ReadGroup(dir)) != NULL) + { + char desc[64]; + getGroupDesc(dirInfo->d_name, desc, sizeof(desc)); + listView->AddItem(new GroupItem(headerView, listView, dirInfo->d_name, desc)); + } + + CloseGroups(dir); + } +} + +void GroupsItem::ListItemSelected() +{ + btnEdit->SetEnabled(true); + btnRemove->SetEnabled(true); +} + +void GroupsItem::ListItemDeselected() +{ + btnEdit->SetEnabled(false); + btnRemove->SetEnabled(false); +} + +void GroupsItem::ListItemUpdated(int index, ListItem *item) +{ + ColumnListView *list = GetAssociatedList(); + char desc[64]; + + getGroupDesc((char *) item->GetColumnContentText(1), desc, sizeof(desc)); + + list->LockLooper(); + item->SetColumnContent(2, desc); + list->InvalidateItem(index); + list->UnlockLooper(); +} + +void GroupsItem::BuildHeader() +{ + BRect r; + BView *headerView = GetAssociatedHeader(); + if (headerView) + { + r.Set(10, 55, 90, 75); + headerView->AddChild(new BButton(r, "AddUserBtn", "Add Group", new BMessage(MSG_GROUP_NEW))); + + r.Set(100, 55, 180, 75); + btnEdit = new BButton(r, "EditUserBtn", "Edit Group", new BMessage(MSG_GROUP_EDIT)); + btnEdit->SetEnabled(false); + headerView->AddChild(btnEdit); + + r.Set(190, 55, 280, 75); + btnRemove = new BButton(r, "RemoveUserBtn", "Remove Group", new BMessage(MSG_GROUP_GONE)); + btnRemove->SetEnabled(false); + headerView->AddChild(btnRemove); + } +} + +bool GroupsItem::HeaderMessageReceived(BMessage *msg) +{ + GroupPropertiesPanel *info; + status_t exitStatus; + BRect r; + BRect frame = GetAssociatedHeader()->Window()->Frame(); + r.Set(frame.left + 150, frame.top + 25, frame.left + 520, frame.top + 375); + + SmartColumnListView *listView = (SmartColumnListView *) GetAssociatedList(); + GroupItem *item = NULL; + int index = listView->CurrentSelection(); + if (index >= 0) + item = (GroupItem *) listView->ItemAt(index); + + switch (msg->what) + { + case MSG_GROUP_NEW: + info = new GroupPropertiesPanel(r, NULL, NULL); + wait_for_thread(info->Thread(), &exitStatus); + if (!info->isCancelled()) + { + listView->LockLooper(); + listView->AddItem(new GroupItem(GetAssociatedHeader(), listView, info->getGroup(), info->getDesc())); + listView->UnlockLooper(); + } + break; + + case MSG_GROUP_EDIT: + if (item) + if (item->ItemInvoked()) + ListItemUpdated(index, item); + break; + + case MSG_GROUP_GONE: + if (item) + listView->DeleteItem(index, item); + break; + + default: + return false; + } + + return false; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Groups.d b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Groups.d new file mode 100644 index 0000000000..4bcb0b317a --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Groups.d @@ -0,0 +1,27 @@ +Groups.o : /boot/home/BeServed/source/BeManager/Groups.cpp \ + /boot/develop/headers/be/app/Application.h \ + /boot/develop/headers/be/storage/Resources.h \ + /boot/develop/headers/be/interface/Window.h \ + /boot/develop/headers/be/interface/View.h \ + /boot/develop/headers/be/interface/Region.h \ + /boot/develop/headers/be/interface/Alert.h \ + /boot/develop/headers/be/interface/Button.h \ + /boot/develop/headers/be/storage/FindDirectory.h \ + /boot/develop/headers/be/storage/Mime.h \ + /boot/develop/headers/posix/string.h \ + /boot/develop/headers/posix/dirent.h \ + /boot/home/dev/Santas\ gift\ bag/ColumnListView/ColumnListView.h \ + /boot/home/dev/Santas\ gift\ bag/Colors.h \ + /boot/home/dev/Santas\ gift\ bag/ColumnListView/CLVColumn.h \ + /boot/home/dev/Santas\ gift\ bag/PrefilledBitmap/PrefilledBitmap.h \ + /boot/home/dev/Santas\ gift\ bag/BetterScrollView/BetterScrollView.h \ + /boot/home/dev/Santas\ gift\ bag/ScrollViewCorner/ScrollViewCorner.h \ + /boot/home/dev/Santas\ gift\ bag/ColumnListView/CLVListItem.h \ + /boot/home/dev/Santas\ gift\ bag/ColumnListView/CLVEasyItem.h \ + /boot/home/dev/Santas\ gift\ bag/NewStrings/NewStrings.h \ + /boot/home/BeServed/source/BeManager/TreeControl.h \ + /boot/home/BeServed/source/BeManager/ListControl.h \ + /boot/home/BeServed/source/BeManager/Groups.h \ + /boot/home/BeServed/source/BeManager/GroupProperties.h \ + /boot/home/BeServed/source/BeManager/Icons.h \ + /boot/home/BeServed/source/BeManager/besure_auth.h diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Groups.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Groups.h new file mode 100644 index 0000000000..f0894eee2e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Groups.h @@ -0,0 +1,38 @@ +// ----- GroupItem ---------------------------------------------------------------------- + +class GroupItem : public ListItem +{ + public: + GroupItem(BView *headerView, ColumnListView *listView, const char *text0, const char *text1); + ~GroupItem(); + + bool ItemInvoked(); + void ItemSelected(); + void ItemDeselected(); + void ItemDeleted(); + bool IsDeleteable(); + + private: + ColumnListView *list; +}; + + +// ----- GroupsItem ----------------------------------------------------- + +class GroupsItem : public TreeItem +{ + public: + GroupsItem(uint32 level, bool superitem, bool expanded, int32 resourceID, BView *headerView, ColumnListView *listView, char *text); + + void ItemSelected(); + void ListItemSelected(); + void ListItemDeselected(); + void ListItemUpdated(int index, ListItem *item); + bool HeaderMessageReceived(BMessage *msg); + + private: + void BuildHeader(); + + BButton *btnEdit; + BButton *btnRemove; +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Icons.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Icons.h new file mode 100644 index 0000000000..4d79c53cc2 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Icons.h @@ -0,0 +1,18 @@ +#define ICON_HOST_LARGE 101 +#define ICON_SHARE_LARGE 102 +#define ICON_HOST_SMALL 103 +#define ICON_SHARE_SMALL 104 +#define ICON_INETHOST_LARGE 105 +#define ICON_INETHOST_SMALL 106 +#define ICON_NETADMIN_LARGE 107 +#define ICON_NETADMIN_SMALL 108 +#define ICON_DOMAIN_LARGE 109 +#define ICON_DOMAIN_SMALL 110 +#define ICON_USER_LARGE 111 +#define ICON_USER_SMALL 112 +#define ICON_BMC_LARGE 113 +#define ICON_BMC_SMALL 114 +#define ICON_GROUP_LARGE 115 +#define ICON_GROUP_SMALL 116 +#define ICON_SERVICES_LARGE 117 +#define ICON_SERVICES_SMALL 118 diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ListControl.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ListControl.cpp new file mode 100644 index 0000000000..0287d4037c --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ListControl.cpp @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include "Mime.h" + +#include "string.h" + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVListItem.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#include "ListControl.h" + + +//static rgb_color active = { 155, 155, 255, 255 }; +//static rgb_color inactive = { 220, 220, 220, 255 }; + + +ListItem::ListItem(BView *headerView, const char *text0, const char *text1, const char *text2) : + CLVEasyItem(0, false, false, 20.0) +{ + SetAssociatedHeader(headerView); + SetColumnContent(1, text0); + SetColumnContent(2, text1); + SetColumnContent(3, text2); +} + +ListItem::~ListItem() +{ +} + +bool ListItem::ItemInvoked() +{ + return false; +} + +void ListItem::ItemSelected() +{ +} + +void ListItem::ItemDeselected() +{ +} + +void ListItem::ItemDeleted() +{ +} + +bool ListItem::IsDeleteable() +{ + return false; +} + + +// ----- SmartColumnListView ---------------------------------------------------------------- + +SmartColumnListView::SmartColumnListView(BRect Frame, CLVContainerView** ContainerView, + const char *Name, uint32 ResizingMode, uint32 flags, list_view_type Type, + bool hierarchical, bool horizontal, bool vertical, bool scroll_view_corner, + border_style border, const BFont* LabelFont) : + ColumnListView(Frame, ContainerView, Name, ResizingMode, flags, Type, hierarchical, + horizontal, vertical, scroll_view_corner, border, LabelFont) +{ + container = *ContainerView; +// SetItemSelectColor(true, active); +// SetItemSelectColor(false, inactive); +} + +SmartColumnListView::~SmartColumnListView() +{ +} + +void SmartColumnListView::MouseDown(BPoint point) +{ + ColumnListView::MouseDown(point); + if (CurrentSelection() < 0) + container->Window()->PostMessage(MSG_LIST_DESELECT); +} + +void SmartColumnListView::KeyUp(const char *bytes, int32 numBytes) +{ + if (*bytes == B_DELETE) + { + int index = CurrentSelection(); + if (index >= 0) + { + ListItem *item = (ListItem *) ItemAt(index); + DeleteItem(index, item); + } + } +} + +bool SmartColumnListView::DeleteItem(int index, ListItem *item) +{ + if (!item->IsDeleteable()) + return true; + + LockLooper(); + RemoveItem(index); + UnlockLooper(); + + item->ItemDeleted(); + + if (CountItems() > 0) + { + Select(max(--index, 0)); + return true; + } + + return false; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ListControl.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ListControl.h new file mode 100644 index 0000000000..9cbe9f06e2 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ListControl.h @@ -0,0 +1,50 @@ +#ifndef max +#define max(a,b) ((a)>=(b)?(a):(b)) +#endif + +class ListItem : public CLVEasyItem +{ + public: + ListItem(BView *headerView, const char *text0, const char *text1, const char *text2); + ~ListItem(); + + BView *GetAssociatedHeader() { return assocHeaderView; } + void SetAssociatedHeader(BView *header) { assocHeaderView = header; } + + virtual bool ItemInvoked(); + virtual void ItemSelected(); + virtual void ItemDeselected(); + virtual void ItemDeleted(); + virtual bool IsDeleteable(); + + private: + BView *assocHeaderView; +}; + + +class SmartColumnListView : public ColumnListView +{ + public: + SmartColumnListView(BRect Frame, CLVContainerView** ContainerView, + const char* Name = NULL, uint32 ResizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, + list_view_type Type = B_SINGLE_SELECTION_LIST, + bool hierarchical = false, bool horizontal = true, bool vertical = true, + bool scroll_view_corner = true, border_style border = B_NO_BORDER, + const BFont* LabelFont = be_plain_font); + + virtual ~SmartColumnListView(); + + // Event handlers (what makes it "smart"). + void MouseDown(BPoint point); + void KeyUp(const char *bytes, int32 numBytes); + + // Helper functions. + bool DeleteItem(int index, ListItem *item); + + private: + CLVContainerView *container; +}; + + +extern const int32 MSG_LIST_DESELECT; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/PickUser.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/PickUser.cpp new file mode 100644 index 0000000000..496545bf15 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/PickUser.cpp @@ -0,0 +1,232 @@ +#include "Application.h" +#include "Resources.h" +#include "Window.h" +#include "View.h" +#include "Region.h" +#include "Button.h" +#include "CheckBox.h" +#include "TextControl.h" +#include "Bitmap.h" +#include "Mime.h" +#include "FilePanel.h" +#include "Menu.h" +#include "PopUpMenu.h" +#include "MenuItem.h" +#include "MenuField.h" +#include "String.h" + +#include "dirent.h" + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVListItem.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#include "ListControl.h" +#include "GroupProperties.h" +#include "PickUser.h" +#include "Icons.h" +#include "besure_auth.h" + +const int32 MSG_PICKUSER_OK = 'GOky'; +const int32 MSG_PICKUSER_CANCEL = 'GCan'; +const int32 MSG_PICKUSER_SELECT = 'MSel'; + + +// ----- PickUserItem ------------------------------------------------------------ + +PickUserItem::PickUserItem(BView *headerView, const char *text0, const char *text1) : + ListItem(headerView, text0, text1, "") +{ + BBitmap *icon; + BMessage archive; + size_t size; + + char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_USER_SMALL, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + { + icon = new BBitmap(&archive); + + SetAssociatedHeader(headerView); + SetColumnContent(0, icon, 2.0); + SetColumnContent(1, text0); + SetColumnContent(2, text1); + } +} + +PickUserItem::~PickUserItem() +{ +} + +void PickUserItem::ItemSelected() +{ +} + +void PickUserItem::ItemDeselected() +{ +} + + +// ----- PickUserView ----------------------------------------------------- + +PickUserView::PickUserView(BRect rect, char *group) : + BView(rect, "PickUserView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + strcpy(excludedGroup, group); + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect r; + r.Set(125, 310, 195, 330); + okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_PICKUSER_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(205, 310, 275, 330); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_PICKUSER_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); + + // Now add the membership list. + CLVContainerView *listContView; + r.Set(13, 48, 275 - B_V_SCROLL_BAR_WIDTH, 300); + listView = new SmartColumnListView(r, &listContView, NULL, B_FOLLOW_ALL_SIDES, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST, + false, false, true, false, B_FANCY_BORDER); + + listView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT)); + listView->AddColumn(new CLVColumn("User", 85.0, CLV_SORT_KEYABLE, 50.0)); + listView->AddColumn(new CLVColumn("Full Name", 130.0, CLV_SORT_KEYABLE)); + + listView->SetSelectionMessage(new BMessage(MSG_PICKUSER_SELECT)); + listView->SetInvocationMessage(new BMessage(MSG_LIST_DESELECT)); + + AddUserList(listView); + AddChild(listContView); +} + +PickUserView::~PickUserView() +{ +} + +void PickUserView::Draw(BRect rect) +{ + BRect r = Bounds(); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(10, 12); + DrawString("Select a user from the list below, then click the OK button."); + MovePenTo(10, 24); + DrawString("Click the Cancel button to abort the selection."); + + MovePenTo(13, 43); + DrawString("Users:"); +} + +void PickUserView::AddUserList(ColumnListView* listView) +{ + DIR *users; + struct dirent *user; + + users = OpenUsers(); + if (users) + { + while ((user = ReadUser(users)) != NULL) + if (!isUserInGroup(user->d_name, excludedGroup)) + { + char desc[64]; + getUserFullName(user->d_name, desc, sizeof(desc)); + listView->AddItem(new PickUserItem(this, user->d_name, desc)); + } + + CloseGroup(users); + } +} + +char *PickUserView::GetSelectedUser() +{ + if (listView) + { + int index = listView->CurrentSelection(); + if (index >= 0) + { + PickUserItem *item = (PickUserItem *) listView->ItemAt(index); + return ((char *) item->GetColumnContentText(1)); + } + } + + return NULL; +} + +void PickUserView::ItemSelected() +{ + okBtn->SetEnabled(true); +} + +void PickUserView::ItemDeselected() +{ + okBtn->SetEnabled(false); +} + + +// ----- PickUserPanel ---------------------------------------------------------------------- + +PickUserPanel::PickUserPanel(BRect frame, char *group) : + BWindow(frame, "Select User", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) +{ + BRect r = Bounds(); + infoView = new PickUserView(r, group); + AddChild(infoView); + + Show(); +} + +// GetUser() +// +char *PickUserPanel::GetUser() +{ + if (user[0]) + return user; + + return NULL; +} + +// MessageReceived() +// +void PickUserPanel::MessageReceived(BMessage *msg) +{ + switch (msg->what) + { + case MSG_PICKUSER_OK: + strcpy(user, infoView->GetSelectedUser()); + BWindow::Quit(); + break; + + case MSG_PICKUSER_CANCEL: + user[0] = 0; + BWindow::Quit(); + break; + + case MSG_PICKUSER_SELECT: + infoView->ItemSelected(); + break; + + case (int32) 'CLV0': //MSG_LIST_DESELECT: + infoView->ItemDeselected(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/PickUser.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/PickUser.h new file mode 100644 index 0000000000..6a3f0a4c03 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/PickUser.h @@ -0,0 +1,44 @@ +// ----- PickUserItem ---------------------------------------------------------------------- + +class PickUserItem : public ListItem +{ + public: + PickUserItem(BView *headerView, const char *text0, const char *text1); + ~PickUserItem(); + + void ItemSelected(); + void ItemDeselected(); +}; + + +class PickUserView : public BView +{ + public: + PickUserView(BRect rect, char *group); + ~PickUserView(); + + void Draw(BRect rect); + char *GetSelectedUser(); + void ItemSelected(); + void ItemDeselected(); + + private: + void AddUserList(ColumnListView* listView); + + SmartColumnListView *listView; + BButton *okBtn; + char excludedGroup[33]; +}; + +class PickUserPanel : public BWindow +{ + public: + PickUserPanel(BRect frame, char *group); + + void MessageReceived(BMessage *msg); + char *GetUser(); + + private: + PickUserView *infoView; + char user[33]; +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Resource.rsrc b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Resource.rsrc new file mode 100644 index 0000000000..5b6438b1fb Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Resource.rsrc differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ServerProperties.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ServerProperties.cpp new file mode 100644 index 0000000000..5b4e26e624 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ServerProperties.cpp @@ -0,0 +1,159 @@ +#include "Application.h" +#include "Resources.h" +#include "Window.h" +#include "View.h" +#include "Region.h" +#include "Button.h" +#include "CheckBox.h" +#include "TextControl.h" +#include "Bitmap.h" +#include "Mime.h" +#include "FilePanel.h" +#include "Menu.h" +#include "PopUpMenu.h" +#include "MenuItem.h" +#include "MenuField.h" +#include "String.h" + +#include "dirent.h" + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVListItem.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#include "ListControl.h" +#include "PickUser.h" +#include "ServerProperties.h" +#include "Icons.h" +#include "besure_auth.h" + +const int32 MSG_SERVER_OK = 'SOky'; +const int32 MSG_SERVER_CANCEL = 'SCan'; +const int32 MSG_SERVER_NEWKEY = 'SKey'; +const int32 MSG_SERVER_JOIN = 'SJon'; + + +// ----- ServerPropertiesView ----------------------------------------------------- + +ServerPropertiesView::ServerPropertiesView(BRect rect, const char *name) : + BView(rect, "GroupInfoView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + strcpy(server, name); + recordLogins = isServerRecordingLogins(server); + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.BeServed-fileserver"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r(10, 64, 250, 84); + chkRecordLogins = new BCheckBox(r, "RecordLogins", "Record all login attempts on this server", new BMessage(MSG_SERVER_JOIN)); + chkRecordLogins->SetValue(recordLogins ? B_CONTROL_ON : B_CONTROL_OFF); + AddChild(chkRecordLogins); + + r.Set(10, 87, 170, 107); + btnViewLogins = new BButton(r, "ViewLogBtn", "View Login Attempts", new BMessage(MSG_SERVER_NEWKEY), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + btnViewLogins->SetEnabled(recordLogins); + AddChild(btnViewLogins); + + r.Set(205, 127, 275, 147); + BButton *okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_SERVER_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(285, 127, 360, 147); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_SERVER_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); +} + +ServerPropertiesView::~ServerPropertiesView() +{ +} + +void ServerPropertiesView::Draw(BRect rect) +{ + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + BString string(server); + string += " Properties"; + DrawString(string.String()); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("This server has certain properties which govern its domain"); + MovePenTo(55, 40); + DrawString("membership and allow authentication servers to mitigate access"); + MovePenTo(55, 52); + DrawString("to resources which it exports."); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); +} + +void ServerPropertiesView::EnableControls() +{ + recordLogins = chkRecordLogins->Value() == B_CONTROL_ON; + btnViewLogins->SetEnabled(recordLogins); +} + + +// ----- ServerPropertiesPanel ---------------------------------------------------------------------- + +ServerPropertiesPanel::ServerPropertiesPanel(BRect frame, const char *name, BWindow *parent) : + BWindow(frame, name, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) +{ + strcpy(server, name); + shareWin = parent; + cancelled = true; + + BRect r = Bounds(); + infoView = new ServerPropertiesView(r, server); + AddChild(infoView); + + Show(); +} + +// MessageReceived() +// +void ServerPropertiesPanel::MessageReceived(BMessage *msg) +{ + switch (msg->what) + { + case MSG_SERVER_OK: + cancelled = false; + setServerRecordingLogins(server, infoView->GetRecordingLogins()); + BWindow::Quit(); + break; + + case MSG_SERVER_CANCEL: + cancelled = true; + BWindow::Quit(); + break; + + case MSG_SERVER_JOIN: + infoView->EnableControls(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ServerProperties.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ServerProperties.h new file mode 100644 index 0000000000..40a1d45079 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/ServerProperties.h @@ -0,0 +1,35 @@ +class ServerPropertiesView : public BView +{ + public: + ServerPropertiesView(BRect rect, const char *name); + ~ServerPropertiesView(); + + void Draw(BRect rect); + void EnableControls(); + + bool GetRecordingLogins() { return recordLogins; } + + private: + BBitmap *icon; + BCheckBox *chkRecordLogins; + BButton *btnViewLogins; + + char server[B_FILE_NAME_LENGTH]; + bool recordLogins; +}; + +class ServerPropertiesPanel : public BWindow +{ + public: + ServerPropertiesPanel(BRect frame, const char *name, BWindow *parent); + + void MessageReceived(BMessage *msg); + + bool isCancelled() { return cancelled; } + + private: + ServerPropertiesView *infoView; + BWindow *shareWin; + char server[B_FILE_NAME_LENGTH]; + bool cancelled; +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Servers.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Servers.cpp new file mode 100644 index 0000000000..e1009c0364 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Servers.cpp @@ -0,0 +1,188 @@ +#include "Application.h" +#include "Resources.h" +#include "Window.h" +#include "View.h" +#include "Region.h" +#include "Alert.h" +#include "Button.h" +#include "FindDirectory.h" +#include "Mime.h" + +#include "string.h" +#include "dirent.h" + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVListItem.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#include "TreeControl.h" +#include "ListControl.h" +#include "Servers.h" +#include "ServerProperties.h" +#include "Icons.h" +#include "besure_auth.h" + +void recvServerName(char *name, uint32 addr); + +const int32 MSG_SERVER_EDIT = 'SEdt'; + +ColumnListView *globalListView = NULL; +BView *globalHeaderView = NULL; + + +ServerItem::ServerItem(BView *headerView, ColumnListView *listView, const char *text0) : + ListItem(headerView, text0, "", "") +{ + BBitmap *icon; + BMessage archive; + size_t size; + + list = listView; + + char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_HOST_SMALL, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + { + icon = new BBitmap(&archive); + + SetColumnContent(0, icon, 2.0); + SetColumnContent(1, text0); + } +} + +ServerItem::~ServerItem() +{ +} + +bool ServerItem::ItemInvoked() +{ + BRect r; + BRect frame = GetAssociatedHeader()->Window()->Frame(); +// status_t exitStatus; + + r.Set(frame.left + 150, frame.top + 25, frame.left + 520, frame.top + 182); // 370 x 350 + ServerPropertiesPanel *info = new ServerPropertiesPanel(r, GetColumnContentText(1), NULL); +// wait_for_thread(info->Thread(), &exitStatus); + return true; +// return (!info->isCancelled()); +} + +void ServerItem::ItemSelected() +{ +} + +void ServerItem::ItemDeselected() +{ +} + +void ServerItem::ItemDeleted() +{ +} + +bool ServerItem::IsDeleteable() +{ + return false; +} + + +ServersItem::ServersItem(uint32 level, bool superitem, bool expanded, int32 resourceID, BView *headerView, ColumnListView *listView, char *text) : + TreeItem(level, superitem, expanded, resourceID, headerView, listView, text) +{ +} + +void ServersItem::ItemSelected() +{ + ColumnListView *listView; + BView *headerView; + + PurgeRows(); + PurgeColumns(); + PurgeHeader(); + BuildHeader(); + + listView = GetAssociatedList(); + headerView = GetAssociatedHeader(); + + listView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT)); + listView->AddColumn(new CLVColumn("Server", 100.0, CLV_SORT_KEYABLE, 50.0)); + + globalHeaderView = headerView; + globalListView = listView; + GetServerList(recvServerName); +} + +void ServersItem::ListItemSelected() +{ + btnEdit->SetEnabled(true); +} + +void ServersItem::ListItemDeselected() +{ + btnEdit->SetEnabled(false); +} + +void ServersItem::ListItemUpdated(int index, ListItem *item) +{ + ColumnListView *list = GetAssociatedList(); + +// getGroupDesc((char *) item->GetColumnContentText(1), desc, sizeof(desc)); + + list->LockLooper(); +// item->SetColumnContent(2, desc); + list->InvalidateItem(index); + list->UnlockLooper(); +} + +void ServersItem::BuildHeader() +{ + BRect r; + BView *headerView = GetAssociatedHeader(); + if (headerView) + { + r.Set(10, 55, 90, 75); + btnEdit = new BButton(r, "EditServerBtn", "Properties", new BMessage(MSG_SERVER_EDIT)); + btnEdit->SetEnabled(false); + headerView->AddChild(btnEdit); + } +} + +bool ServersItem::HeaderMessageReceived(BMessage *msg) +{ + BRect r; + BRect frame = GetAssociatedHeader()->Window()->Frame(); + r.Set(frame.left + 150, frame.top + 25, frame.left + 520, frame.top + 375); + + SmartColumnListView *listView = (SmartColumnListView *) GetAssociatedList(); + ServerItem *item = NULL; + int index = listView->CurrentSelection(); + if (index >= 0) + item = (ServerItem *) listView->ItemAt(index); + + switch (msg->what) + { + case MSG_SERVER_EDIT: + if (item) + if (item->ItemInvoked()) + ListItemUpdated(index, item); + break; + + default: + return false; + } + + return false; +} + + +void recvServerName(char *name, uint32 addr) +{ + if (globalListView) + { + globalListView->LockLooper(); + globalListView->AddItem(new ServerItem(globalHeaderView, globalListView, name)); + globalListView->UnlockLooper(); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Servers.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Servers.h new file mode 100644 index 0000000000..742144d844 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Servers.h @@ -0,0 +1,37 @@ +// ----- ServerItem ---------------------------------------------------------------------- + +class ServerItem : public ListItem +{ + public: + ServerItem(BView *headerView, ColumnListView *listView, const char *text0); + ~ServerItem(); + + bool ItemInvoked(); + void ItemSelected(); + void ItemDeselected(); + void ItemDeleted(); + bool IsDeleteable(); + + private: + ColumnListView *list; +}; + + +// ----- ServersItem ----------------------------------------------------- + +class ServersItem : public TreeItem +{ + public: + ServersItem(uint32 level, bool superitem, bool expanded, int32 resourceID, BView *headerView, ColumnListView *listView, char *text); + + void ItemSelected(); + void ListItemSelected(); + void ListItemDeselected(); + void ListItemUpdated(int index, ListItem *item); + bool HeaderMessageReceived(BMessage *msg); + + private: + void BuildHeader(); + + BButton *btnEdit; +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/TreeControl.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/TreeControl.cpp new file mode 100644 index 0000000000..5a1bc4c3d4 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/TreeControl.cpp @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include +#include "Mime.h" + +#include "string.h" + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVListItem.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#include "TreeControl.h" + +//static rgb_color active = { 155, 155, 255, 255 }; +//static rgb_color inactive = { 220, 220, 220, 255 }; + + +SmartTreeListView::SmartTreeListView(BRect Frame, CLVContainerView** ContainerView, + const char *Name, uint32 ResizingMode, uint32 flags, list_view_type Type, + bool hierarchical, bool horizontal, bool vertical, bool scroll_view_corner, + border_style border, const BFont* LabelFont) : + ColumnListView(Frame, ContainerView, Name, ResizingMode, flags, Type, hierarchical, + horizontal, vertical, scroll_view_corner, border, LabelFont) +{ + container = *ContainerView; +// SetItemSelectColor(true, active); +// SetItemSelectColor(false, inactive); +} + +SmartTreeListView::~SmartTreeListView() +{ +} + +void SmartTreeListView::MouseUp(BPoint point) +{ + int curSelection = CurrentSelection(); + ColumnListView::MouseUp(point); + if (curSelection >= 0 && curSelection != lastSelection) + { + TreeItem *item = (TreeItem *) ItemAt(curSelection); + item->ItemSelected(); + lastSelection = curSelection; + } +} + +void SmartTreeListView::Expand(TreeItem *item) +{ + ColumnListView::Expand((CLVEasyItem *) item); + item->ItemExpanding(); +} + + + +TreeItem::TreeItem(uint32 level, bool superitem, bool expanded, int32 resourceID, BView *headerView, ColumnListView *listView, char *text) : + CLVListItem(level, superitem, expanded, 16.0) +{ + SetAssociatedHeader(headerView); + SetAssociatedList(listView); + + setIcon(resourceID); + fText = new char[strlen(text) + 1]; + strcpy(fText, text); +} + +TreeItem::~TreeItem() +{ + delete [] fText; +} + +void TreeItem::setIcon(int32 resourceID) +{ + BMessage archive; + size_t size; + char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), resourceID, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + fIcon = new BBitmap(&archive); +} + +void TreeItem::DrawItemColumn(BView* owner, BRect item_column_rect, int32 column_index, bool complete) +{ + rgb_color color; + bool selected = IsSelected(); + + if (selected) + color = BeListSelectGrey; + else + color = White; + + owner->SetLowColor(color); + owner->SetDrawingMode(B_OP_COPY); + + if (selected || complete) + { + owner->SetHighColor(color); + owner->FillRect(item_column_rect); + } + + BRegion Region; + Region.Include(item_column_rect); + owner->ConstrainClippingRegion(&Region); + owner->SetHighColor(Black); + + if (column_index == 1) + { + item_column_rect.left += 2.0; + item_column_rect.right = item_column_rect.left + 15.0; + item_column_rect.top += 2.0; + if (Height() > 20.0) + item_column_rect.top += ceil((Height() - 20.0) / 2.0); + item_column_rect.bottom = item_column_rect.top + 15.0; + owner->SetDrawingMode(B_OP_OVER); + owner->DrawBitmap(fIcon, BRect(0.0, 0.0, 15.0, 15.0), item_column_rect); + owner->SetDrawingMode(B_OP_COPY); + } + else if(column_index == 2) + owner->DrawString(fText, + BPoint(item_column_rect.left + 2.0, item_column_rect.top + fTextOffset)); + + owner->ConstrainClippingRegion(NULL); +} + +void TreeItem::Update(BView *owner, const BFont *font) +{ + CLVListItem::Update(owner, font); + font_height FontAttributes; + be_plain_font->GetHeight(&FontAttributes); + float FontHeight = ceil(FontAttributes.ascent) + ceil(FontAttributes.descent); + fTextOffset = ceil(FontAttributes.ascent) + (Height() - FontHeight) / 2.0; +} + +int TreeItem::MyCompare(const CLVListItem* a_Item1, const CLVListItem* a_Item2, int32 KeyColumn) +{ + char *text1 = ((TreeItem*)a_Item1)->fText; + char *text2 = ((TreeItem*)a_Item2)->fText; + return strcasecmp(text1, text2); +} + +void TreeItem::ItemSelected() +{ + PurgeRows(); + PurgeColumns(); + PurgeHeader(); +} + +void TreeItem::ItemExpanding() +{ +} + +void TreeItem::ListItemSelected() +{ +} + +void TreeItem::ListItemDeselected() +{ +} + +void TreeItem::ListItemUpdated(int index, CLVListItem *item) +{ +} + +void TreeItem::PurgeHeader() +{ + if (assocHeaderView) + { + int children = assocHeaderView->CountChildren(); + assocHeaderView->LockLooper(); + + for (int i = children - 1; i >= 0; i--) + { + BView *child = assocHeaderView->ChildAt(i); + assocHeaderView->RemoveChild(child); + delete child; + } + + assocHeaderView->UnlockLooper(); + } +} + +void TreeItem::PurgeColumns() +{ + if (assocListView) + { + int columns = assocListView->CountColumns(); + if (columns > 0) + assocListView->RemoveColumns(assocListView->ColumnAt(0), columns); + } +} + +void TreeItem::PurgeRows() +{ + if (assocListView) + { + int rows = assocListView->CountItems(); + if (rows > 0) + assocListView->RemoveItems(0, rows); + } +} + +bool TreeItem::HeaderMessageReceived(BMessage *msg) +{ + return false; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/TreeControl.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/TreeControl.h new file mode 100644 index 0000000000..8d1775c4c2 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/TreeControl.h @@ -0,0 +1,59 @@ +class TreeItem : public CLVListItem +{ + public: + TreeItem(uint32 level, bool superitem, bool expanded, int32 resourceID, BView *headerView, ColumnListView *listView, char* text); + ~TreeItem(); + void DrawItemColumn(BView* owner, BRect item_column_rect, int32 column_index, bool complete); + void Update(BView *owner, const BFont *font); + static int MyCompare(const CLVListItem* a_Item1, const CLVListItem* a_Item2, int32 KeyColumn); + + ColumnListView *GetAssociatedList() { return assocListView; } + void SetAssociatedList(ColumnListView *list) { assocListView = list; } + + BView *GetAssociatedHeader() { return assocHeaderView; } + void SetAssociatedHeader(BView *header) { assocHeaderView = header; } + + virtual void ItemSelected(); + virtual void ItemExpanding(); + virtual void ListItemSelected(); + virtual void ListItemDeselected(); + virtual void ListItemUpdated(int index, CLVListItem *item); + virtual bool HeaderMessageReceived(BMessage *msg); + + protected: + void PurgeRows(); + void PurgeColumns(); + void PurgeHeader(); + + private: + void setIcon(int32 resourceID); + + BView *assocHeaderView; + ColumnListView *assocListView; + BBitmap* fIcon; + char *fText; + float fTextOffset; +}; + +// ----- SmartTreeListView ---------------------------------------------------------------- + +class SmartTreeListView : public ColumnListView +{ + public: + SmartTreeListView(BRect Frame, CLVContainerView** ContainerView, + const char* Name = NULL, uint32 ResizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, + list_view_type Type = B_SINGLE_SELECTION_LIST, + bool hierarchical = false, bool horizontal = true, bool vertical = true, + bool scroll_view_corner = true, border_style border = B_NO_BORDER, + const BFont* LabelFont = be_plain_font); + + virtual ~SmartTreeListView(); + + void MouseUp(BPoint point); + void Expand(TreeItem *item); + + private: + CLVContainerView *container; + int lastSelection; +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/UserProperties.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/UserProperties.cpp new file mode 100644 index 0000000000..8f182b5901 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/UserProperties.cpp @@ -0,0 +1,318 @@ +#include "Application.h" +#include "Window.h" +#include "View.h" +#include "Region.h" +#include "Button.h" +#include "CheckBox.h" +#include "TextControl.h" +#include "Bitmap.h" +#include "Mime.h" +#include "FilePanel.h" +#include "Menu.h" +#include "PopUpMenu.h" +#include "MenuItem.h" +#include "MenuField.h" +#include "String.h" +#include "Entry.h" +#include "Path.h" + +#include "dirent.h" +#include "stdio.h" + +#include "UserProperties.h" +#include "besure_auth.h" + +const int32 MSG_USER_OK = 'UOky'; +const int32 MSG_USER_CANCEL = 'UCan'; +const int32 MSG_USER_BROWSE = 'UBrw'; +const int32 MSG_USER_REFRESH = 'URef'; + +// ----- UserPropertiesView ----------------------------------------------------- + +UserPropertiesView::UserPropertiesView(BRect rect, const char *name) : + BView(rect, "HostInfoView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + BMenuItem *item; + char strDays[10]; + + days = flags = 0; + newUser = name == NULL; + strcpy(user, newUser ? "unknown" : name); + getUserFullName(user, fullName, sizeof(fullName)); + getUserDesc(user, desc, sizeof(desc)); + getUserPassword(user, password, sizeof(password)); + getUserFlags(user, &flags); + getUserDaysToExpire(user, &days); + getUserHome(user, home, sizeof(home)); + getUserGroup(user, group, sizeof(group)); + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.Teldar-User"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r(10, 52, 200, 72); + editName = new BTextControl(r, "UserName", "Name:", user, NULL); + editName->SetDivider(75); + editName->SetEnabled(newUser); + AddChild(editName); + + r.Set(10, 77, 250, 97); + editFullName = new BTextControl(r, "FullName", "Full Name:", fullName, NULL); + editFullName->SetDivider(75); + AddChild(editFullName); + + r.Set(10, 102, 250, 122); + editDesc = new BTextControl(r, "Description", "Description:", desc, NULL); + editDesc->SetDivider(75); + AddChild(editDesc); + + r.Set(10, 127, 200, 147); + editPassword = new BTextControl(r, "Password", "Password:", password, NULL); + editPassword->SetDivider(75); + editPassword->TextView()->HideTyping(true); + AddChild(editPassword); + + r.top = 157; + r.bottom = r.top + 15; + chkDisabled = new BCheckBox(r, "Disabled", "Account is disabled", NULL); + chkDisabled->SetValue(flags & USER_FLAG_DISABLED ? B_CONTROL_ON : B_CONTROL_OFF); + chkDisabled->SetEnabled(false); + AddChild(chkDisabled); + + r.top = 177; + r.bottom = r.top + 15; + chkExpiresFirst = new BCheckBox(r, "Expires", "Password expires on first use", NULL); + chkExpiresFirst->SetValue(flags & USER_FLAG_INIT_EXPIRE ? B_CONTROL_ON : B_CONTROL_OFF); + chkExpiresFirst->SetEnabled(false); + AddChild(chkExpiresFirst); + + r.top = 197; + r.bottom = r.top + 15; + chkExpiresEvery = new BCheckBox(r, "ExpireEvery", "Password expires every", NULL); + chkExpiresEvery->SetValue(flags & USER_FLAG_DAYS_EXPIRE ? B_CONTROL_ON : B_CONTROL_OFF); + chkExpiresEvery->SetEnabled(false); + AddChild(chkExpiresEvery); + + r.Set(150, 197, 190, 217); + sprintf(strDays, "%lu", days); + editDays = new BTextControl(r, "ExpireDays", "", strDays, NULL); + editDays->SetDivider(0); + editDays->SetEnabled(false); + AddChild(editDays); + + r.left = 10; + r.top = 217; + r.bottom = r.top + 15; + chkCantChange = new BCheckBox(r, "CantChange", "User cannot change password", NULL); + chkCantChange->SetValue(flags & USER_FLAG_PW_LOCKED ? B_CONTROL_ON : B_CONTROL_OFF); + chkCantChange->SetEnabled(false); + AddChild(chkCantChange); + + r.top = 242; + r.bottom = r.top + 20; + r.right = 270; + editPath = new BTextControl(r, "HomePath", "Home Path:", home, NULL); + editPath->SetDivider(75); + AddChild(editPath); + + r.Set(280, 239, 360, 259); + AddChild(new BButton(r, "BrowseBtn", "Browse...", new BMessage(MSG_USER_BROWSE))); + + mnuGroups = new BPopUpMenu(""); + DIR *groups = OpenGroups(); + if (groups) + { + dirent_t *group; + while ((group = ReadGroup(groups)) != NULL) + mnuGroups->AddItem(new BMenuItem(group->d_name, NULL)); + + CloseGroups(groups); + } + + r.Set(10, 270, 200, 290); + mnuDefaultGroup = new BMenuField(r, "DefaultGroup", "Default Group:", mnuGroups); + mnuDefaultGroup->SetDivider(75); + item = mnuGroups->FindItem(group); + if (item) + item->SetMarked(true); + AddChild(mnuDefaultGroup); + + r.Set(205, 320, 275, 340); + BButton *okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_USER_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(285, 320, 360, 340); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_USER_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); +} + +UserPropertiesView::~UserPropertiesView() +{ +} + +void UserPropertiesView::Draw(BRect rect) +{ + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color disabled = { 120, 120, 120, 255 }; + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + BString string(user); + string += " Properties"; + DrawString(string.String()); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("The properties of this user account govern how it is to be used"); + MovePenTo(55, 40); + DrawString("and the rules the authentication server applies to its maintenance."); + + if (!editDays->IsEnabled()) + SetHighColor(disabled); + MovePenTo(202, 210); + DrawString("days"); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); +} + +void UserPropertiesView::UpdateInfo() +{ + if (newUser) + strcpy(user, editName->Text()); + + strcpy(fullName, editFullName->Text()); + strcpy(desc, editDesc->Text()); + strcpy(password, editPassword->Text()); + strcpy(home, editPath->Text()); + + flags = 0; + if (chkDisabled->Value() == B_CONTROL_ON) + flags |= USER_FLAG_DISABLED; + if (chkExpiresFirst->Value() == B_CONTROL_ON) + flags |= USER_FLAG_INIT_EXPIRE; + if (chkExpiresEvery->Value() == B_CONTROL_ON) + flags |= USER_FLAG_DAYS_EXPIRE; + if (chkCantChange->Value() == B_CONTROL_ON) + flags |= USER_FLAG_PW_LOCKED; + + BMenuItem *item = mnuGroups->FindMarked(); + if (item) + strcpy(group, item->Label()); +} + +// SetPath() +// +void UserPropertiesView::SetPath(const char *path) +{ + if (editPath && path) + { + editPath->LockLooper(); + editPath->SetText(path); + editPath->UnlockLooper(); + } +} + + +// ----- UserPropertiesPanel ---------------------------------------------------------------------- + +UserPropertiesPanel::UserPropertiesPanel(BRect frame, const char *name, BWindow *parent) : + BWindow(frame, name, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) +{ + newUser = name == NULL; + if (!newUser) + strcpy(user, name); + + shareWin = parent; + cancelled = true; + + BRect r = Bounds(); + infoView = new UserPropertiesView(r, name == NULL ? NULL : user); + AddChild(infoView); + + myMsgr = new BMessenger(NULL, this, NULL); + Show(); +} + +// MessageReceived() +// +void UserPropertiesPanel::MessageReceived(BMessage *msg) +{ + BFilePanel *filePanel; + entry_ref entryRef; + BPath path; + + BEntry entry("/boot/home", false); + entry.GetRef(&entryRef); + + switch (msg->what) + { + case MSG_USER_BROWSE: + filePanel = new BFilePanel(B_OPEN_PANEL, myMsgr, &entryRef, B_DIRECTORY_NODE, false); +// filePanel->SetTarget(this); + filePanel->Show(); + filePanel->Window()->SetTitle("User Home"); + filePanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select"); + break; + + case B_REFS_RECEIVED: + msg->FindRef("refs", &entryRef); + entry.SetTo(&entryRef, true); + entry.GetPath(&path); + infoView->SetPath(path.Path()); + break; + + case MSG_USER_OK: + cancelled = false; + infoView->UpdateInfo(); + if (newUser) + { + strcpy(user, infoView->getUser()); + createUser(user, infoView->getPassword()); + setUserGroup(user, infoView->getGroup()); + } + else + { + char group[64]; + getUserGroup(user, group, sizeof(group)); + removeUserFromGroup(user, group); + setUserGroup(user, infoView->getGroup()); + } + + strcpy(fullName, infoView->getFullName()); + strcpy(desc, infoView->getDesc()); + + setUserFullName(user, infoView->getFullName()); + setUserDesc(user, infoView->getDesc()); + setUserPassword(user, infoView->getPassword()); + setUserHome(user, infoView->getHome()); + setUserFlags(user, infoView->getFlags()); + BWindow::Quit(); + break; + + case MSG_USER_CANCEL: + cancelled = true; + BWindow::Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/UserProperties.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/UserProperties.h new file mode 100644 index 0000000000..4e45320c12 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/UserProperties.h @@ -0,0 +1,70 @@ +class UserPropertiesView : public BView +{ + public: + UserPropertiesView(BRect rect, const char *name); + ~UserPropertiesView(); + + void Draw(BRect rect); + void UpdateInfo(); + void SetPath(const char *path); + + char *getUser() { return user; } + char *getFullName() { return fullName; } + char *getDesc() { return desc; } + char *getPassword() { return password; } + char *getHome() { return home; } + char *getGroup() { return group; } + uint32 getFlags() { return flags; } + uint32 getDays() { return days; } + + private: + BBitmap *icon; + BTextControl *editName; + BTextControl *editFullName; + BTextControl *editDesc; + BTextControl *editPassword; + BTextControl *editPath; + BTextControl *editDays; + BCheckBox *chkDisabled; + BCheckBox *chkExpiresFirst; + BCheckBox *chkExpiresEvery; + BCheckBox *chkCantChange; + BMenu *mnuGroups; + BMenuField *mnuDefaultGroup; + + char user[33]; + char fullName[64]; + char desc[64]; + char password[33]; + char home[B_PATH_NAME_LENGTH]; + char group[33]; + uint32 flags; + uint32 days; + + bool newUser; +}; + + +class UserPropertiesPanel : public BWindow +{ + public: + UserPropertiesPanel(BRect frame, const char *name, BWindow *parent); + + void MessageReceived(BMessage *msg); + + char *getUser() { return user; } + char *getFullName() { return fullName; } + char *getDesc() { return desc; } + bool isCancelled() { return cancelled; } + + private: + BMessenger *myMsgr; + UserPropertiesView *infoView; + BWindow *shareWin; + char user[33]; + char fullName[64]; + char desc[64]; + + bool newUser; + bool cancelled; +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Users.cpp b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Users.cpp new file mode 100644 index 0000000000..ad00cd3023 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Users.cpp @@ -0,0 +1,227 @@ +#include "Application.h" +#include "Resources.h" +#include "Window.h" +#include "View.h" +#include "Region.h" +#include "Alert.h" +#include "Button.h" +#include "FindDirectory.h" +#include "Mime.h" + +#include "string.h" +#include "dirent.h" + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVListItem.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#include "TreeControl.h" +#include "ListControl.h" +#include "Users.h" +#include "UserProperties.h" +#include "Icons.h" +#include "besure_auth.h" + +#define WARN_REMOVE_USER "Removing this user account may prevent access to network resources and may permanently relinquish any rights held. Are you sure you want to remove this user?" + +const int32 MSG_USER_NEW = 'UNew'; +const int32 MSG_USER_EDIT = 'UEdt'; +const int32 MSG_USER_GONE = 'UGon'; + + +UserItem::UserItem(BView *headerView, const char *text0, const char *text1, const char *text2) : + ListItem(headerView, text0, text1, text2) +{ + BBitmap *icon; + BMessage archive; + size_t size; + + char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_USER_SMALL, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + { + icon = new BBitmap(&archive); + + SetAssociatedHeader(headerView); + SetColumnContent(0, icon, 2.0); + SetColumnContent(1, text0); + SetColumnContent(2, text1); + SetColumnContent(3, text2); + } +} + +UserItem::~UserItem() +{ +} + +bool UserItem::ItemInvoked() +{ + BRect r; + BRect frame = GetAssociatedHeader()->Window()->Frame(); + status_t exitStatus; + + r.Set(frame.left + 150, frame.top + 25, frame.left + 520, frame.top + 375); // 370 x 350 + UserPropertiesPanel *info = new UserPropertiesPanel(r, GetColumnContentText(1), NULL); + wait_for_thread(info->Thread(), &exitStatus); + return (!info->isCancelled()); +} + +void UserItem::ItemSelected() +{ +} + +void UserItem::ItemDeselected() +{ +} + +void UserItem::ItemDeleted() +{ + removeUser((char *) GetColumnContentText(1)); +} + +bool UserItem::IsDeleteable() +{ + BAlert *alert = new BAlert("Remove User?", WARN_REMOVE_USER, "Yes", "No"); + alert->SetShortcut(1, B_ESCAPE); + alert->SetShortcut(0, 'y'); + alert->SetShortcut(1, 'n'); + return (alert->Go() == 0); +} + + +UsersItem::UsersItem(uint32 level, bool superitem, bool expanded, int32 resourceID, BView *headerView, ColumnListView *listView, char *text) : + TreeItem(level, superitem, expanded, resourceID, headerView, listView, text) +{ +} + +void UsersItem::ItemSelected() +{ + DIR *dir; + struct dirent *dirInfo; + ColumnListView *listView; + BView *headerView; + + PurgeRows(); + PurgeColumns(); + PurgeHeader(); + BuildHeader(); + + listView = GetAssociatedList(); + headerView = GetAssociatedHeader(); + + listView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT)); + listView->AddColumn(new CLVColumn("User", 85.0, CLV_SORT_KEYABLE, 50.0)); + listView->AddColumn(new CLVColumn("Full Name", 130.0, CLV_SORT_KEYABLE)); + listView->AddColumn(new CLVColumn("Description", 150.0, CLV_SORT_KEYABLE)); + + dir = OpenUsers(); + if (dir) + { + while ((dirInfo = ReadUser(dir)) != NULL) + { + char fullName[64], desc[64]; + getUserFullName(dirInfo->d_name, fullName, sizeof(fullName)); + getUserDesc(dirInfo->d_name, desc, sizeof(desc)); + listView->AddItem(new UserItem(headerView, dirInfo->d_name, fullName, desc)); + } + + CloseUsers(dir); + } +} + +void UsersItem::ListItemSelected() +{ + btnEdit->SetEnabled(true); + btnRemove->SetEnabled(true); +} + +void UsersItem::ListItemDeselected() +{ + btnEdit->SetEnabled(false); + btnRemove->SetEnabled(false); +} + +void UsersItem::ListItemUpdated(int index, ListItem *item) +{ + ColumnListView *list = GetAssociatedList(); + char *user = (char *) item->GetColumnContentText(1); + char fullName[64], desc[64]; + + getUserFullName(user, fullName, sizeof(fullName)); + getUserDesc(user, desc, sizeof(desc)); + + list->LockLooper(); + item->SetColumnContent(2, fullName); + item->SetColumnContent(3, desc); + list->InvalidateItem(index); + list->UnlockLooper(); +} + +void UsersItem::BuildHeader() +{ + BRect r; + BView *headerView = GetAssociatedHeader(); + if (headerView) + { + r.Set(10, 55, 90, 75); + headerView->AddChild(new BButton(r, "AddUserBtn", "Add User", new BMessage(MSG_USER_NEW))); + + r.Set(100, 55, 180, 75); + btnEdit = new BButton(r, "EditUserBtn", "Edit User", new BMessage(MSG_USER_EDIT)); + btnEdit->SetEnabled(false); + headerView->AddChild(btnEdit); + + r.Set(190, 55, 280, 75); + btnRemove = new BButton(r, "RemoveUserBtn", "Remove User", new BMessage(MSG_USER_GONE)); + btnRemove->SetEnabled(false); + headerView->AddChild(btnRemove); + } +} + +bool UsersItem::HeaderMessageReceived(BMessage *msg) +{ + UserPropertiesPanel *info; + status_t exitStatus; + BRect r; + BRect frame = GetAssociatedHeader()->Window()->Frame(); + r.Set(frame.left + 150, frame.top + 25, frame.left + 520, frame.top + 375); + + SmartColumnListView *listView = (SmartColumnListView *) GetAssociatedList(); + UserItem *item = NULL; + int index = listView->CurrentSelection(); + if (index >= 0) + item = (UserItem *) listView->ItemAt(index); + + switch (msg->what) + { + case MSG_USER_NEW: + info = new UserPropertiesPanel(r, NULL, NULL); + wait_for_thread(info->Thread(), &exitStatus); + if (!info->isCancelled()) + { + listView->LockLooper(); + listView->AddItem(new UserItem(GetAssociatedHeader(), info->getUser(), info->getFullName(), info->getDesc())); + listView->UnlockLooper(); + } + break; + + case MSG_USER_EDIT: + if (item) + if (item->ItemInvoked()) + ListItemUpdated(index, item); + break; + + case MSG_USER_GONE: + if (item) + listView->DeleteItem(index, item); + break; + + default: + return false; + } + + return false; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Users.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Users.h new file mode 100644 index 0000000000..053ff3ad8d --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/Users.h @@ -0,0 +1,35 @@ +// ----- UserItem ---------------------------------------------------------------------- + +class UserItem : public ListItem +{ + public: + UserItem(BView *headerView, const char *text0, const char *text1, const char *text2); + ~UserItem(); + + bool ItemInvoked(); + void ItemSelected(); + void ItemDeselected(); + void ItemDeleted(); + bool IsDeleteable(); +}; + + +// ----- UsersItem ----------------------------------------------------- + +class UsersItem : public TreeItem +{ + public: + UsersItem(uint32 level, bool superitem, bool expanded, int32 resourceID, BView *headerView, ColumnListView *listView, char *text); + + void ItemSelected(); + void ListItemSelected(); + void ListItemDeselected(); + void ListItemUpdated(int index, ListItem *item); + bool HeaderMessageReceived(BMessage *msg); + + private: + void BuildHeader(); + + BButton *btnEdit; + BButton *btnRemove; +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/besure_auth.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/besure_auth.h new file mode 100644 index 0000000000..003ed4ec66 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/besure_auth.h @@ -0,0 +1,75 @@ +#ifndef _BESURE_AUTH_H_ +#define _BESURE_AUTH_H_ + +#include + +#define USER_FLAG_DISABLED 0x00000001 +#define USER_FLAG_INIT_EXPIRE 0x00000002 +#define USER_FLAG_DAYS_EXPIRE 0x00000004 +#define USER_FLAG_PW_LOCKED 0x00000008 + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +typedef void (*recordServerFunc)(char *name, uint32 addr); + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE bool createUser(char *user, char *password); +_IMPEXP_BESURE bool createGroup(char *group); +_IMPEXP_BESURE bool removeUser(char *user); +_IMPEXP_BESURE bool removeGroup(char *group); +_IMPEXP_BESURE bool addUserToGroup(char *user, char *group); +_IMPEXP_BESURE bool removeUserFromGroup(char *user, char *group); +_IMPEXP_BESURE bool isUserInGroup(char *user, char *group); + +_IMPEXP_BESURE bool setUserFullName(char *user, char *fullName); +_IMPEXP_BESURE bool setUserDesc(char *user, char *desc); +_IMPEXP_BESURE bool setUserPassword(char *user, char *password); +_IMPEXP_BESURE bool setUserFlags(char *user, uint32 flags); +_IMPEXP_BESURE bool setUserDaysToExpire(char *user, uint32 days); +_IMPEXP_BESURE bool setUserHome(char *user, char *home); +_IMPEXP_BESURE bool setUserGroup(char *user, char *group); +_IMPEXP_BESURE bool setGroupDesc(char *group, char *desc); + +_IMPEXP_BESURE bool getUserFullName(char *user, char *fullName, int bufSize); +_IMPEXP_BESURE bool getUserDesc(char *user, char *desc, int bufSize); +_IMPEXP_BESURE bool getUserPassword(char *user, char *password, int bufSize); +_IMPEXP_BESURE bool getUserFlags(char *user, uint32 *flags); +_IMPEXP_BESURE bool getUserDaysToExpire(char *user, uint32 *days); +_IMPEXP_BESURE bool getUserHome(char *user, char *home, int bufSize); +_IMPEXP_BESURE bool getUserGroup(char *user, char *group, int bufSize); +_IMPEXP_BESURE bool getGroupDesc(char *group, char *desc, int bufSize); + +_IMPEXP_BESURE bool isServerRecordingLogins(char *server); +_IMPEXP_BESURE bool setServerRecordingLogins(char *server, bool recording); + +_IMPEXP_BESURE void MakeServerKey(char *server, char *key); + +_IMPEXP_BESURE DIR *OpenUsers(); +_IMPEXP_BESURE dirent_t *ReadUser(DIR *dir); +_IMPEXP_BESURE void CloseUsers(DIR *dir); +_IMPEXP_BESURE DIR *OpenGroups(); +_IMPEXP_BESURE dirent_t *ReadGroup(DIR *dir); +_IMPEXP_BESURE void CloseGroups(DIR *dir); +_IMPEXP_BESURE DIR *OpenGroup(char *group); +_IMPEXP_BESURE dirent_t *ReadGroupMember(DIR *dir); +_IMPEXP_BESURE void CloseGroup(DIR *dir); +_IMPEXP_BESURE int GetServerList(recordServerFunc recServ); + +_IMPEXP_BESURE bool GetKeyValue(const char *fileName, const char *key, char *value, int bufSize); +_IMPEXP_BESURE bool GetKeyInt(const char *fileName, const char *key, int *value); +_IMPEXP_BESURE bool SetKeyValue(const char *fileName, const char *key, const char *value); +_IMPEXP_BESURE bool SetKeyInt(const char *fileName, const char *key, int value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/betalk.h new file mode 100644 index 0000000000..af38d0d926 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +// The different types of network resources supported by BeServed. +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRITNER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 32768 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 128 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int nsid; + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +typedef struct rpcInfo +{ + thread_id rpcThread; + int32 quitXID; + + uint32 serverIP; + int32 serverPort; + int s; +} bt_rpcinfo; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket inPacket; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/md5.c b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/md5.c new file mode 100644 index 0000000000..92f51d890b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/md5.c @@ -0,0 +1,408 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id: md5.c $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include "stdio.h" +#include "md5.h" + +#ifdef TEST +/* + * Compile with -DTEST to create a self-contained executable test program. + * The test program should print out the same values as given in section + * A.5 of RFC 1321, reproduced below. + */ +#include +main() +{ + static const char *const test[7] = { + "", /*d41d8cd98f00b204e9800998ecf8427e*/ + "a", /*0cc175b9c0f1b6a831c399e269772661*/ + "abc", /*900150983cd24fb0d6963f7d28e17f72*/ + "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/ + "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + /*d174ab98d277d9f5a5611c2c9f419d9f*/ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/ + }; + int i; + + for (i = 0; i < 7; ++i) { + md5_state_t state; + md5_byte_t digest[16]; + int di; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); + md5_finish(&state, digest); + printf("MD5 (\"%s\") = ", test[i]); + for (di = 0; di < 16; ++di) + printf("%02x", digest[di]); + printf("\n"); + } + return 0; +} +#endif /* TEST */ + + +/* + * For reference, here is the program that computed the T values. + */ +#if 0 +#include +main() +{ + int i; + for (i = 1; i <= 64; ++i) { + unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); + printf("#define T%d 0x%08lx\n", i, v); + } + return 0; +} +#endif + +void md5EncodeString(const char *source, char *dest) +{ + md5_state_t state; + md5_byte_t digest[16]; + int i; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *) source, strlen(source)); + md5_finish(&state, digest); + + for (i = 0; i < 16; i++) + sprintf(dest + (i * 2), "%02x", digest[i]); +} + +/* + * End of T computation program. + */ +#define T1 0xd76aa478 +#define T2 0xe8c7b756 +#define T3 0x242070db +#define T4 0xc1bdceee +#define T5 0xf57c0faf +#define T6 0x4787c62a +#define T7 0xa8304613 +#define T8 0xfd469501 +#define T9 0x698098d8 +#define T10 0x8b44f7af +#define T11 0xffff5bb1 +#define T12 0x895cd7be +#define T13 0x6b901122 +#define T14 0xfd987193 +#define T15 0xa679438e +#define T16 0x49b40821 +#define T17 0xf61e2562 +#define T18 0xc040b340 +#define T19 0x265e5a51 +#define T20 0xe9b6c7aa +#define T21 0xd62f105d +#define T22 0x02441453 +#define T23 0xd8a1e681 +#define T24 0xe7d3fbc8 +#define T25 0x21e1cde6 +#define T26 0xc33707d6 +#define T27 0xf4d50d87 +#define T28 0x455a14ed +#define T29 0xa9e3e905 +#define T30 0xfcefa3f8 +#define T31 0x676f02d9 +#define T32 0x8d2a4c8a +#define T33 0xfffa3942 +#define T34 0x8771f681 +#define T35 0x6d9d6122 +#define T36 0xfde5380c +#define T37 0xa4beea44 +#define T38 0x4bdecfa9 +#define T39 0xf6bb4b60 +#define T40 0xbebfbc70 +#define T41 0x289b7ec6 +#define T42 0xeaa127fa +#define T43 0xd4ef3085 +#define T44 0x04881d05 +#define T45 0xd9d4d039 +#define T46 0xe6db99e5 +#define T47 0x1fa27cf8 +#define T48 0xc4ac5665 +#define T49 0xf4292244 +#define T50 0x432aff97 +#define T51 0xab9423a7 +#define T52 0xfc93a039 +#define T53 0x655b59c3 +#define T54 0x8f0ccc92 +#define T55 0xffeff47d +#define T56 0x85845dd1 +#define T57 0x6fa87e4f +#define T58 0xfe2ce6e0 +#define T59 0xa3014314 +#define T60 0x4e0811a1 +#define T61 0xf7537e82 +#define T62 0xbd3af235 +#define T63 0x2ad7d2bb +#define T64 0xeb86d391 + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; + +#ifndef ARCH_IS_BIG_ENDIAN +# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ +#endif +#if ARCH_IS_BIG_ENDIAN + + /* + * On big-endian machines, we must arrange the bytes in the right + * order. (This also works on machines of unknown byte order.) + */ + md5_word_t X[16]; + const md5_byte_t *xp = data; + int i; + + for (i = 0; i < 16; ++i, xp += 4) + X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + +#else /* !ARCH_IS_BIG_ENDIAN */ + + /* + * On little-endian machines, we can process properly aligned data + * without copying it. + */ + md5_word_t xbuf[16]; + const md5_word_t *X; + + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } +#endif + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = 0xefcdab89; + pms->abcd[2] = 0x98badcfe; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeManager/md5.h b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/md5.h new file mode 100644 index 0000000000..b9522e80f9 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeManager/md5.h @@ -0,0 +1,96 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id: md5.h $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This code has some adaptations for the Ghostscript environment, but it + * will compile and run correctly in any environment with 8-bit chars and + * 32-bit ints. Specifically, it assumes that if the following are + * defined, they have the same meaning as in Ghostscript: P1, P2, P3, + * ARCH_IS_BIG_ENDIAN. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +void md5EncodeString(const char *source, char *dest); + +/* Initialize the algorithm. */ +#ifdef P1 +void md5_init(P1(md5_state_t *pms)); +#else +void md5_init(md5_state_t *pms); +#endif + +/* Append a string to the message. */ +#ifdef P3 +void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); +#else +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +#endif + +/* Finish the message and return the digest. */ +#ifdef P2 +void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); +#else +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeSure/BeSureServer.proj b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/BeSureServer.proj new file mode 100644 index 0000000000..7e78b7fc32 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/BeSureServer.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeSure/BeSureServer_BONE.proj b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/BeSureServer_BONE.proj new file mode 100644 index 0000000000..c31f9b9c26 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/BeSureServer_BONE.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeSure/BlowFish.h b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/BlowFish.h new file mode 100644 index 0000000000..cfc5667dd3 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/BlowFish.h @@ -0,0 +1,35 @@ +/* blowfish.h */ + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +#define UWORD32 unsigned long +#define UBYTE08 unsigned char + +#define MAXKEYBYTES 56 /* 448 bits */ + +typedef struct +{ + unsigned long S[4][256], P[18]; +} blf_ctx; + +unsigned long F(blf_ctx *, unsigned long x); +void Blowfish_encipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +void Blowfish_decipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +short InitializeBlowfish(blf_ctx *, unsigned char key[], int keybytes); + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE void blf_enc(blf_ctx *c, unsigned long *data, int blocks); +_IMPEXP_BESURE void blf_dec(blf_ctx *c, unsigned long *data, int blocks); +_IMPEXP_BESURE void blf_key(blf_ctx *c, unsigned char *key, int len); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeSure/Resource.rsrc b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/Resource.rsrc new file mode 100644 index 0000000000..3e21412bfb Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/Resource.rsrc differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeSure/besure_auth.h b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/besure_auth.h new file mode 100644 index 0000000000..0a3a551871 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/besure_auth.h @@ -0,0 +1,75 @@ +#ifndef _BESURE_AUTH_H_ +#define _BESURE_AUTH_H_ + +#include + +#define USER_FLAG_DISABLED 0x00000001 +#define USER_FLAG_INIT_EXPIRE 0x00000002 +#define USER_FLAG_DAYS_EXPIRE 0x00000004 +#define USER_FLAG_PW_LOCKED 0x00000008 + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +typedef void (*recordServerFunc)(char *name, uint32 addr); + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE bool createUser(char *user, char *password); +_IMPEXP_BESURE bool createGroup(char *group); +_IMPEXP_BESURE bool removeUser(char *user); +_IMPEXP_BESURE bool removeGroup(char *group); +_IMPEXP_BESURE bool addUserToGroup(char *user, char *group); +_IMPEXP_BESURE bool removeUserFromGroup(char *user, char *group); +_IMPEXP_BESURE bool isUserInGroup(char *user, char *group); + +_IMPEXP_BESURE bool setUserFullName(char *user, char *fullName); +_IMPEXP_BESURE bool setUserDesc(char *user, char *desc); +_IMPEXP_BESURE bool setUserPassword(char *user, char *password); +_IMPEXP_BESURE bool setUserFlags(char *user, uint32 flags); +_IMPEXP_BESURE bool setUserDaysToExpire(char *user, uint32 days); +_IMPEXP_BESURE bool setUserHome(char *user, char *home); +_IMPEXP_BESURE bool setUserGroup(char *user, char *group); +_IMPEXP_BESURE bool setGroupDesc(char *group, char *desc); + +_IMPEXP_BESURE bool getUserFullName(char *user, char *fullName, int bufSize); +_IMPEXP_BESURE bool getUserDesc(char *user, char *desc, int bufSize); +_IMPEXP_BESURE bool getUserPassword(char *user, char *password, int bufSize); +_IMPEXP_BESURE bool getUserFlags(char *user, uint32 *flags); +_IMPEXP_BESURE bool getUserDaysToExpire(char *user, uint32 *days); +_IMPEXP_BESURE bool getUserHome(char *user, char *home, int bufSize); +_IMPEXP_BESURE bool getUserGroup(char *user, char *group, int bufSize); +_IMPEXP_BESURE bool getGroupDesc(char *group, char *desc, int bufSize); + +_IMPEXP_BESURE bool isServerRecordingLogins(char *server); +_IMPEXP_BESURE bool setServerRecordingLogins(char *server, bool recording); + +_IMPEXP_BESURE void MakeServerKey(char *server, char *key); + +_IMPEXP_BESURE DIR *OpenUsers(); +_IMPEXP_BESURE dirent_t *ReadUser(DIR *dir); +_IMPEXP_BESURE void CloseUsers(DIR *dir); +_IMPEXP_BESURE DIR *OpenGroups(); +_IMPEXP_BESURE dirent_t *ReadGroup(DIR *dir); +_IMPEXP_BESURE void CloseGroups(DIR *dir); +_IMPEXP_BESURE DIR *OpenGroup(char *group); +_IMPEXP_BESURE dirent_t *ReadGroupMember(DIR *dir); +_IMPEXP_BESURE void CloseGroup(DIR *dir); +_IMPEXP_BESURE int GetServerList(recordServerFunc recServ); + +_IMPEXP_BESURE bool GetKeyValue(const char *fileName, const char *key, char *value, int bufSize); +_IMPEXP_BESURE bool GetKeyInt(const char *fileName, const char *key, int *value); +_IMPEXP_BESURE bool SetKeyValue(const char *fileName, const char *key, const char *value); +_IMPEXP_BESURE bool SetKeyInt(const char *fileName, const char *key, int value); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeSure/besure_server.c b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/besure_server.c new file mode 100644 index 0000000000..b619404026 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/besure_server.c @@ -0,0 +1,1041 @@ +// btAdd.cpp : Defines the entry point for the console application. +// + +#include "FindDirectory.h" + +#include "betalk.h" +#include "sysdepdefs.h" +#include "besure_auth.h" +#include "BlowFish.h" + +#include "netdb.h" +#include "utime.h" +#include "ctype.h" +#include "time.h" +#include "signal.h" +#include "stdlib.h" +#include "syslog.h" + +#define BT_MAX_THREADS 128 +#define BT_MAX_RETRIES 3 +#define BT_THREAD_NAME "BeSure Handler" + +typedef struct +{ + unsigned int type; + unsigned int length; + char *data; +} bt_arg_t; + +typedef struct session +{ + int socket; + unsigned int client_s_addr; + thread_id handlerID; + struct session *next; +} bt_session_t; + +typedef void (*bt_net_func)(bt_session_t *, unsigned int, int, bt_arg_t *); + +typedef struct dirCommand +{ + unsigned char command; + bt_net_func handler; + bool supported; + uint8 args; + uint32 argTypes[MAX_COMMAND_ARGS]; +} bt_command_t; + + +int main(int argc, char *argv[]); +void daemonInit(); +void startService(); +void endService(); +void restartService(); +int32 requestThread(void *data); +int receiveRequest(bt_session_t *session); +void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]); +void launchThread(int client, struct sockaddr_in *addr); +void sendErrorToClient(int client, unsigned int xid, int error); +void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); + +void btLock(sem_id semaphore, int32 *atomic); +void btUnlock(sem_id semaphore, int32 *atomic); + +int generateTicket(const char *client, const char *server, unsigned char *key, char *ticket); +void recordLogin(char *server, char *share, char *client, bool authenticated); +void strlwr(char *str); + +int cmdAuthenticate(unsigned int addr, char *client, char *token, char *response); +int cmdReadUsers(DIR **dir, char *user, char *fullName); +int cmdReadGroups(DIR **dir, char *group); +int cmdWhichGroups(DIR **dir, char *user, char *group); + +void netcmdAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netcmdReadUsers(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netcmdReadGroups(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netcmdWhichGroups(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netcmdQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); + +bt_session_t *rootSession = NULL; +bool running = true; +int server; +sem_id sessionSem; +int32 sessionVar; + +bt_command_t dirCommands[] = +{ + { BT_CMD_AUTH, netcmdAuthenticate, true, 2, { B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_READUSERS, netcmdReadUsers, true, 1, { B_INT32_TYPE } }, + { BT_CMD_READGROUPS, netcmdReadGroups, true, 1, { B_INT32_TYPE } }, + { BT_CMD_WHICHGROUPS, netcmdWhichGroups, true, 1, { B_STRING_TYPE } }, + { BT_CMD_QUIT, netcmdQuit, true, 0, { 0 } }, + { 0, NULL, false, 0, { 0 } } +}; + + +int main(int argc, char *argv[]) +{ + daemonInit(); + + signal(SIGINT, endService); + signal(SIGTERM, endService); + signal(SIGHUP, restartService); + signal(SIGPIPE, SIG_IGN); + + if ((sessionSem = create_sem(0, "Session Semaphore")) > 0) + { + // Run the daemon. We will not return until the service is being stopped. + startService(); + delete_sem(sessionSem); + } + + return 0; +} + +void daemonInit() +{ + int i; + + // Cause the parent task to terminate, freeing the terminal. + if (fork() != 0) + exit(0); + + // In the child process, become the session leader. + setsid(); + + // Now fork again, causing the first child to exit, since the session + // leader can be assigned a controlling terminal under SVR4. + signal(SIGHUP, SIG_IGN); + if (fork() != 0) + exit(0); + + // Change to the root directory, since if we hold on to a working + // folder that was in a mounted file system, that file system cannot + // be unmounted. + chdir("/"); + + // Reset the file creation mask to zero to eliminate the inherited value. + umask(0); + + // Close open file descriptors. Since we can't know how many of a + // potentially unlimited value can be open, just close the first 64 + // and assume that will be enough. + for (i = 0; i < 64; i++) + close(i); + + // Open the syslog. + openlog("besure_server", LOG_PID, LOG_DAEMON); +} + +void restartService() +{ +} + +void startService() +{ + struct sockaddr_in serverAddr, clientAddr; + int client, addrLen; + int flags; + + // Store the length of the socket addressing structure for accept(). + addrLen = sizeof(struct sockaddr_in); + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(BT_BESURE_PORT); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Create a new socket to receive incoming requests. + server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (server == INVALID_SOCKET) + return; + + // Set the socket option to reuse the current address in case it was + // in use by a prior version of the service that has not yet relinquished + // the socket. + flags = 1; + setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); + + // Bind that socket to the address constructed above. + if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return; + + // Listen for incoming connections. + if (listen(server, 5)) + return; + + // Continually accept incoming connections. When one is found, + // fire off a handler thread to accept commands. + while (running) + { + client = accept(server, (struct sockaddr *) &clientAddr, &addrLen); + if (client != INVALID_SOCKET) + launchThread(client, &clientAddr); + } + + // Close the socket. Technically, I believe we should call shutdown() + // first, but the BeOS header file socket.h indicates that this + // function is not currently working. It is present but may not have + // any effect. + shutdown(server, 2); + closesocket(server); + server = INVALID_SOCKET; +} + +void endService() +{ + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + exit(0); +} + +// launchThread() +// +void launchThread(int client, struct sockaddr_in *addr) +{ + bt_session_t *s, *cur, *last = NULL; + int count = 0; + + // First verify that the server's not too busy by scanning the list of active + // sessions. This is also useful because we need to eliminate unused sessions + // from the list, i.e., sessions that have closed. + btLock(sessionSem, &sessionVar); + + s = rootSession; + while (s) + { + if (s->socket == INVALID_SOCKET) + { + if (last) + last->next = s->next; + else + rootSession = s->next; + + cur = s->next; + free(s); + s = cur; + continue; + } + + last = s; + s = s->next; + count++; + } + + // If the total number of valid sessions was less than our allowed maximum, then + // we can create a new session. + if (count < BT_MAX_THREADS) + { + // We need to create an available session for this connection. + bt_session_t *session = (bt_session_t *) malloc(sizeof(bt_session_t)); + if (session) + { + session->socket = client; + session->client_s_addr = addr->sin_addr.s_addr; + + session->handlerID = + spawn_thread(requestThread, BT_THREAD_NAME, B_NORMAL_PRIORITY, session); + resume_thread(session->handlerID); + + // Add this to the session list. + session->next = rootSession; + rootSession = session; + btUnlock(sessionSem, &sessionVar); + return; + } + } + + btUnlock(sessionSem, &sessionVar); + + // We must have too many threads active, so let the client know we're busy. + sendErrorToClient(client, 0, EBUSY); + shutdown(client, 2); + closesocket(client); +} + +int32 requestThread(void *data) +{ + bt_session_t *session = (bt_session_t *) data; +// int flags; + + if (!session) + return 0; + +// flags = 1; +// setsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags)); + + while (receiveRequest(session)); + + shutdown(session->socket, 2); + closesocket(session->socket); + session->socket = INVALID_SOCKET; + return 0; +} + +int receiveRequest(bt_session_t *session) +{ + bt_inPacket packet; + char signature[20], *buffer; + unsigned char command; + int client, sigLen; + int32 length; + + client = session->socket; + + // Read the BeTalk RPC header. + sigLen = strlen(BT_RPC_SIGNATURE); + if (btRecvMsg(client, signature, sigLen, 0) == -1) + return 0; + +// recv(client, &verHi, sizeof(verHi), 0); +// recv(client, &verLo, sizeof(verLo), 0); + + signature[sigLen] = 0; + if (strcmp(signature, BT_RPC_SIGNATURE)) + return 0; + + // Read in the rest of the packet. + if (btRecvMsg(client, &length, sizeof(int32), 0) == -1) + return 0; + + length = B_LENDIAN_TO_HOST_INT32(length); + if (length == 0 || length > BT_RPC_MAX_PACKET_SIZE) + return 0; + + buffer = (char *) malloc(length + 1); + if (!buffer) + return 0; + + if (btRecvMsg(client, buffer, length, 0) == -1) + { + free(buffer); + return 0; + } + + buffer[length] = 0; + packet.buffer = buffer; + packet.length = length; + packet.offset = 0; + + // Read the transmission ID and command. + command = btRPCGetChar(&packet); + getArguments(session, &packet, command); + free(buffer); + return (command != BT_CMD_AUTH && command != BT_CMD_QUIT); +} + +void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command) +{ + bt_arg_t args[MAX_COMMAND_ARGS]; + int i, client; + bool error; + unsigned char argc, terminator; + int32 xid; + + error = false; + client = session->socket; + argc = btRPCGetChar(packet); + if (argc > MAX_COMMAND_ARGS) + return; + + for (i = 0; i < argc && !error; i++) + { + args[i].type = btRPCGetInt32(packet); + args[i].data = btRPCGetNewString(packet); + if (args[i].data == NULL) + error = true; + } + + if (!error) + { + xid = btRPCGetInt32(packet); + terminator = btRPCGetChar(packet); + if (terminator == BT_CMD_TERMINATOR) + handleRequest(session, xid, command, argc, args); + } + else + sendErrorToClient(session->socket, 0, EINVAL); + + while (--i >= 0) + free(args[i].data); +} + +void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]) +{ + bool validated = true; + int i, j; + + for (i = 0; dirCommands[i].handler; i++) + if (command == dirCommands[i].command) + { + // We may have received a valid command, but one that is not supported by this + // server. In this case, we'll want to return an operation not supported error, + // as opposed to an invalid command error. + if (!dirCommands[i].supported) + { + sendErrorToClient(session->socket, xid, EOPNOTSUPP); + return; + } + + // Now verify that the argument count is correct, and if so, the type of all + // arguments is correct. If not, an invalid command error is returned. + // Otherise, the command is executed, and the handler returns any necessary + // acknowledgement. + if (argc == dirCommands[i].args) + { + for (j = 0; j < argc; j++) + if (dirCommands[i].argTypes[j] != argv[j].type) + { + validated = false; + break; + } + + if (validated) + { + (*dirCommands[i].handler)(session, xid, argc, argv); + return; + } + } + } + + sendErrorToClient(session->socket, xid, EINVAL); +} + +void sendErrorToClient(int client, unsigned int xid, int error) +{ + bt_outPacket packet; + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +int btRecvMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesRead = 0; + do + { + int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags); + if (bytes == -1) + return -1; + + bytesRead += bytes; + } while (bytesRead < dataLen); + + return bytesRead; +} + +// btRecv() +// +int btRecv(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = recv(sock, data, dataLen, flags); + if (bytes == 0) + return -1; + else if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +int btSendMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesSent = 0; + do + { + int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags); + if (bytes == -1) + return -1; + + bytesSent += bytes; + } while (bytesSent < dataLen); + + return bytesSent; +} + +// btSend() +// +int btSend(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = send(sock, data, dataLen, flags); + if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error) +{ + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + return; + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + btRPCPutInt32(packet, xid); + btRPCPutInt32(packet, 0); + btRPCPutInt32(packet, error); +} + +void btRPCSendAck(int client, bt_outPacket *packet) +{ + if (packet) + if (packet->buffer) + { + *(int32 *)(&packet->buffer[9]) = B_HOST_TO_LENDIAN_INT32(packet->length - 13); + btSendMsg(client, packet->buffer, packet->length, 0); + free(packet->buffer); + } +} + +unsigned char btRPCGetChar(bt_inPacket *packet) +{ + unsigned char value; + + if (packet->offset < packet->length) + value = (unsigned char) packet->buffer[packet->offset]; + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + if (bytes > 0) + memcpy(str, &packet->buffer[packet->offset], bytes); + + str[bytes] = 0; + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return ERANGE; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return ERANGE; + + if (length < bytes) + return ERANGE; + + if (bytes > 0) + memcpy(buffer, &packet->buffer[packet->offset], bytes); + + packet->offset += bytes; + return bytes; +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +///////////////////////////////////////////////////////////////////// + +void btLock(sem_id semaphore, int32 *atomic) +{ + int32 previous = atomic_add(atomic, 1); + if (previous >= 1) + while (acquire_sem(semaphore) == B_INTERRUPTED); +} + +void btUnlock(sem_id semaphore, int32 *atomic) +{ + int32 previous = atomic_add(atomic, -1); + if (previous > 1) + release_sem(semaphore); +} + +//////////////////////////////////////////////////////////////////// + +int generateTicket(const char *client, const char *server, unsigned char *key, char *ticket) +{ + blf_ctx ctx; + char buffer[128], session[128]; + int length; + + // Generate a session key. + sprintf(session, "%s.%s.%lx", client, server, time(NULL)); + + // Generate the connection ticket. Because the ticket will be encrypted via the + // BlowFish algorithm, it's length must be divisible by four. We can pad the + // buffer with NULL characters so it won't affect the string. + sprintf(buffer, "%s,%s", client, session); + length = strlen(buffer); + while (length % 4) + buffer[length++] = ' '; + + buffer[length] = 0; + blf_key(&ctx, key, strlen(key)); + blf_enc(&ctx, (unsigned long *) buffer, length / 4); + + // Now we have the ticket. It gets wrapped into a response buffer here. + sprintf(ticket, "%s,%s,%s,%s", client, server, session, buffer); + return strlen(ticket); +} + +// strlwr() +// +void strlwr(char *str) +{ + char *p; + for (p = str; *p; p++) + *p = tolower(*p); +} + +//////////////////////////////////////////////////////////////////// + +int cmdAuthenticate(unsigned int addr, char *client, char *token, char *response) +{ + blf_ctx ctx; + char server[B_FILE_NAME_LENGTH + 1], share[B_FILE_NAME_LENGTH + 1], user[MAX_USERNAME_LENGTH + 1]; + char buffer[BT_AUTH_TOKEN_LENGTH * 2 + 1]; + unsigned char clientKey[MAX_KEY_LENGTH + 1]; + int i; + + // Obtain the host name of our peer from the socket information. + struct hostent *ent = gethostbyaddr((const char *) &addr, sizeof(addr), AF_INET); + if (ent) + strcpy(server, ent->h_name); + else + { + uint8 *p = (uint8 *) &addr; + sprintf(server, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + } + +// printf("\tClient = %s\n", client); +// printf("\tToken = %s\n", token); + + // Obtain the specified client's key. + if (!getUserPassword(client, clientKey, sizeof(clientKey))) + return EACCES; + +// printf("\tClient key = %s\n", clientKey); + + // Get the encrypted authentication information. + memcpy(buffer, token, BT_AUTH_TOKEN_LENGTH); + buffer[BT_AUTH_TOKEN_LENGTH] = 0; + + // Now decrypt the request using the client's key. + blf_key(&ctx, clientKey, strlen(clientKey)); + blf_dec(&ctx, (unsigned long *) buffer, BT_AUTH_TOKEN_LENGTH / 4); + +// printf("\tDecrypted buffer = [%s]\n", buffer); + + // The encrypted buffer may have been padded with spaces to make its length + // evenly divisible by four. + i = strlen(buffer); + while (buffer[--i] == ' ' && i >= 0) + buffer[i] = 0; + + // Once decrypted, we can extract the server being contacted. + memcpy(share, buffer, B_FILE_NAME_LENGTH); + for (i = B_FILE_NAME_LENGTH - 1; i && share[i] == ' '; i--); + share[i + 1] = 0; +// printf("\tShare = %s\n", share); + + // The remainder of the buffer is the MD5-encoded client name. + memcpy(user, &buffer[B_FILE_NAME_LENGTH], MAX_USERNAME_LENGTH); + for (i = MAX_USERNAME_LENGTH - 1; i && user[i] == ' '; i--); + user[i + 1] = 0; + +// printf("\tComparing: Client [%s] and tok [%s]\n", client, user); + if (strcmp(client, user) != 0) + { + recordLogin(server, share, client, false); + return EACCES; + } + + recordLogin(server, share, client, true); + generateTicket(client, share, clientKey, response); + + return B_OK; +} + +void recordLogin(char *server, char *share, char *client, bool authenticated) +{ + FILE *fp; + struct tm *localTime; + time_t curTime; + char path[B_PATH_NAME_LENGTH], timeStamp[50]; + + if (!isServerRecordingLogins(server)) + return; + + // Obtain the filename for the log file. + find_directory(B_COMMON_LOG_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/BeServed-Logins.log"); + + // Build the time stamp. + curTime = time(NULL); + localTime = localtime(&curTime); + strftime(timeStamp, sizeof(timeStamp), "%m/%d/%Y %H:%M:%S", localTime); + + fp = fopen(path, "a"); + if (fp) + { + fprintf(fp, "%s: %s [%s] %s %s\n", timeStamp, server, + authenticated ? share : "--", + client, + authenticated ? "authenticated" : "rejected"); + fclose(fp); + } +} + +int cmdReadUsers(DIR **dir, char *user, char *fullName) +{ + struct dirent *dirInfo; + + if (!user || !fullName) + return EINVAL; + + if (!*dir) + *dir = OpenUsers(); + + if (*dir) + if ((dirInfo = ReadUser(*dir)) != NULL) + { + strcpy(user, dirInfo->d_name); + getUserFullName(user, fullName, MAX_DESC_LENGTH); + return B_OK; + } + else + { + CloseUsers(*dir); + return ENOENT; + } + + return EINVAL; +} + +int cmdReadGroups(DIR **dir, char *group) +{ + struct dirent *dirInfo; + + if (!group) + return EINVAL; + + if (!*dir) + *dir = OpenGroups(); + + if (*dir) + if ((dirInfo = ReadGroup(*dir)) != NULL) + { + strcpy(group, dirInfo->d_name); + return B_OK; + } + else + { + CloseGroups(*dir); + return ENOENT; + } + + return EINVAL; +} + +int cmdWhichGroups(DIR **dir, char *user, char *group) +{ + int error = cmdReadGroups(dir, group); + while (error == B_OK) + { + if (isUserInGroup(user, group)) + return B_OK; + + error = cmdReadGroups(dir, group); + } + + return error; +} + +//////////////////////////////////////////////////////////////////// + +void netcmdAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + char response[256]; + + client = session->socket; + + error = cmdAuthenticate(session->client_s_addr, argv[0].data, argv[1].data, response); + btRPCCreateAck(&packet, xid, error); + if (error == B_OK) + btRPCPutString(&packet, response, strlen(response)); + + btRPCSendAck(client, &packet); +} + +void netcmdReadUsers(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + DIR *dir = (DIR *)(*((int32 *) argv[0].data)); + char user[MAX_USERNAME_LENGTH + 1], fullName[MAX_DESC_LENGTH + 1]; + int entries = 0; + + client = session->socket; + + error = cmdReadUsers(&dir, user, fullName); + if (error != B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + btRPCCreateAck(&packet, xid, B_OK); + while (error == B_OK) + { + btRPCPutString(&packet, user, strlen(user)); + btRPCPutString(&packet, fullName, strlen(fullName)); + + if (++entries >= 80) + break; + + error = cmdReadUsers(&dir, user, fullName); + btRPCPutInt32(&packet, error); + } + + // If we exhausted the list of directory entries without filling + // the buffer, add an error message that will prevent the client + // from requesting further entries. + if (entries < 80) + btRPCPutInt32(&packet, ENOENT); + + btRPCSendAck(client, &packet); +} + +void netcmdReadGroups(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + DIR *dir = (DIR *)(*((int32 *) argv[0].data)); + char group[MAX_USERNAME_LENGTH + 1]; + int entries = 0; + + client = session->socket; + + error = cmdReadGroups(&dir, group); + if (error != B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + btRPCCreateAck(&packet, xid, B_OK); + while (error == B_OK) + { + btRPCPutString(&packet, group, strlen(group)); + + if (++entries >= 80) + break; + + error = cmdReadGroups(&dir, group); + btRPCPutInt32(&packet, error); + } + + // If we exhausted the list of directory entries without filling + // the buffer, add an error message that will prevent the client + // from requesting further entries. + if (entries < 80) + btRPCPutInt32(&packet, ENOENT); + + btRPCSendAck(client, &packet); +} + +void netcmdWhichGroups(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + DIR *dir = 0; + char group[MAX_USERNAME_LENGTH + 1]; + int entries = 0; + + client = session->socket; + + error = cmdWhichGroups(&dir, argv[0].data, group); + if (error != B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + btRPCCreateAck(&packet, xid, B_OK); + while (error == B_OK) + { + btRPCPutString(&packet, group, strlen(group)); + + if (++entries >= 80) + break; + + error = cmdWhichGroups(&dir, argv[0].data, group); + btRPCPutInt32(&packet, error); + } + + // If we exhausted the list of directory entries without filling + // the buffer, add an error message that will prevent the client + // from requesting further entries. + if (entries < 80) + btRPCPutInt32(&packet, ENOENT); + + btRPCSendAck(client, &packet); +} + +// netcmdQuit() +// +void netcmdQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, B_OK); + btRPCSendAck(client, &packet); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeSure/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/betalk.h new file mode 100644 index 0000000000..af38d0d926 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +// The different types of network resources supported by BeServed. +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRITNER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 32768 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 128 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int nsid; + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +typedef struct rpcInfo +{ + thread_id rpcThread; + int32 quitXID; + + uint32 serverIP; + int32 serverPort; + int s; +} bt_rpcinfo; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket inPacket; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/BeSure/sysdepdefs.h b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/sysdepdefs.h new file mode 100644 index 0000000000..6bb4bd5051 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/BeSure/sysdepdefs.h @@ -0,0 +1,10 @@ +#ifndef _SYSDEPDEFS_H_ +#define _SYSDEPDEFS_H_ + +#ifdef BONE_VERSION + +#define closesocket(s) close(s) + +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/BeServed-Settings b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/BeServed-Settings new file mode 100644 index 0000000000..b071e3d6e8 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/BeServed-Settings @@ -0,0 +1,4 @@ +authenticate with 10.1.6.15 +share e:\temp as "Temp Folder" +grant read,write on "Temp Folder" to kmusick +grant read on "Temp Folder" to group everyone diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/BrowseFolders.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/BrowseFolders.cpp new file mode 100644 index 0000000000..176cd4d3f5 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/BrowseFolders.cpp @@ -0,0 +1,102 @@ +// BrowseFolders.cpp : implementation file +// + +#include "stdafx.h" + +#include "FileSharing.h" +#include "BrowseFolders.h" +#include "MTVFolder.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBrowseFolders dialog + + +CBrowseFolders::CBrowseFolders(CWnd* pParent /*=NULL*/) + : CDialog(CBrowseFolders::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBrowseFolders) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + m_newPath.Empty(); +} + + +void CBrowseFolders::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBrowseFolders) + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_FOLDERVIEW, m_folderCtrl); +} + + +BEGIN_MESSAGE_MAP(CBrowseFolders, CDialog) + //{{AFX_MSG_MAP(CBrowseFolders) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBrowseFolders message handlers + +BOOL CBrowseFolders::OnInitDialog() +{ + CDialog::OnInitDialog(); + SetPath(m_newPath); + return TRUE; +} + +// SelectFolder() +// +int CBrowseFolders::SelectFolder(LPCTSTR lpszPath) +{ + m_newPath = lpszPath; + return DoModal(); +} + +// SetPath() +// +void CBrowseFolders::SetPath(LPCTSTR lpszPath) +{ + CString string(lpszPath); + VARIANT variant; + BSTR bstr = string.AllocSysString(); + + variant.vt = VT_BSTR; + variant.bstrVal = bstr; + + m_folderCtrl.put_SelectedFolder(variant); +} + +// GetPath() +// +CString CBrowseFolders::GetPath() +{ + if (IsWindow(m_folderCtrl.GetSafeHwnd())) + { + VARIANT var = m_folderCtrl.get_SelectedFolder(); + CMTVFolder folder(var.pdispVal); + return folder.GetPathName(); + } + + return m_newPath; +} + +// OnOK() +// +void CBrowseFolders::OnOK() +{ + VARIANT var = m_folderCtrl.get_SelectedFolder(); + CMTVFolder folder(var.pdispVal); + + m_newPath = folder.GetPathName(); + m_newPath.MakeLower(); + + CDialog::OnOK(); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/BrowseFolders.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/BrowseFolders.h new file mode 100644 index 0000000000..d1b3692be3 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/BrowseFolders.h @@ -0,0 +1,57 @@ +//{{AFX_INCLUDES() +#include "folderview.h" +//}}AFX_INCLUDES +#if !defined(AFX_BROWSEFOLDERS_H__60DF2AD1_F62B_11D5_90FA_00C04F0972A7__INCLUDED_) +#define AFX_BROWSEFOLDERS_H__60DF2AD1_F62B_11D5_90FA_00C04F0972A7__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// BrowseFolders.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CBrowseFolders dialog + +class CBrowseFolders : public CDialog +{ +// Construction +public: + CBrowseFolders(CWnd* pParent = NULL); // standard constructor + + int SelectFolder(LPCTSTR lpszPath); + CString GetPath(); + +// Dialog Data + //{{AFX_DATA(CBrowseFolders) + enum { IDD = IDD_BROWSER }; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBrowseFolders) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + CString m_newPath; + + // Generated message map functions + //{{AFX_MSG(CBrowseFolders) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + void SetPath(LPCTSTR lpszPath); +public: + CFolderview m_folderCtrl; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BROWSEFOLDERS_H__60DF2AD1_F62B_11D5_90FA_00C04F0972A7__INCLUDED_) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/DomainUsers.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/DomainUsers.cpp new file mode 100644 index 0000000000..85739d01e9 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/DomainUsers.cpp @@ -0,0 +1,192 @@ +// DomainUsers.cpp : implementation file +// + +#include "stdafx.h" + +#include "beCompat.h" +#include "betalk.h" +#include "FileSharing.h" +#include "DomainUsers.h" +#include "rpc.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDomainUsers dialog + + +CDomainUsers::CDomainUsers(CWnd* pParent /*=NULL*/) + : CDialog(CDomainUsers::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDomainUsers) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + m_nRights = 0; + m_user.Empty(); + m_bGroup = false; + m_bPrinting = false; +} + + +void CDomainUsers::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDomainUsers) + DDX_Control(pDX, IDOK, m_okayBtn); + DDX_Control(pDX, IDC_DOMAIN_USERS, m_userList); + DDX_Control(pDX, IDC_DOMAIN_RIGHTS, m_rights); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDomainUsers, CDialog) + //{{AFX_MSG_MAP(CDomainUsers) + ON_NOTIFY(NM_CLICK, IDC_DOMAIN_USERS, OnClickDomainUsers) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDomainUsers message handlers + +int CDomainUsers::ShowUsers(bool bPrinting) +{ + SetPrinting(bPrinting); + return DoModal(); +} + +BOOL CDomainUsers::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_userList.SetExtendedStyle(LVS_EX_FULLROWSELECT); + m_userList.InsertColumn(0, "User or Group", LVCFMT_LEFT, 175); + m_userList.InsertColumn(1, "Full Name", LVCFMT_LEFT, 185); + + CBitmap user, group; + user.LoadBitmap(IDB_USER); + group.LoadBitmap(IDB_GROUP); + + m_images.Create(16, 16, FALSE, 2, 0); + m_images.Add(&user, (COLORREF) 0); + m_images.Add(&group, (COLORREF) 0); + m_userList.SetImageList(&m_images, LVSIL_SMALL); + + if (m_bPrinting) + { + m_rights.ResetContent(); + m_rights.AddString("Print"); + } + + AddUserList(); + AddGroupList(); + + return TRUE; +} + +void CDomainUsers::OnClickDomainUsers(NMHDR* pNMHDR, LRESULT* pResult) +{ + int nIndex; + *pResult = 0; + nIndex = GetSelectedListItem(&m_userList); + if (nIndex >= 0) + { + m_rights.EnableWindow(TRUE); + m_rights.SelectString(-1, m_bPrinting ? "Print" : "Read-only"); + m_okayBtn.EnableWindow(TRUE); + } + else + { + m_rights.EnableWindow(FALSE); + m_okayBtn.EnableWindow(FALSE); + } +} + +void CDomainUsers::OnOK() +{ + CString rights; + int nItem = GetSelectedListItem(&m_userList); + m_user = m_userList.GetItemText(nItem, 0); + + m_bGroup = m_userList.GetItemData(nItem) ? true : false; + + m_nRights = m_bPrinting ? BT_RIGHTS_PRINT : BT_RIGHTS_READ; + nItem = m_rights.GetCurSel(); + m_rights.GetLBText(nItem, rights); + if (rights.CompareNoCase("Read-write") == 0) + m_nRights |= BT_RIGHTS_WRITE; + + CDialog::OnOK(); +} + +void CDomainUsers::AddUserList() +{ + extern unsigned int authServerIP; + int32 *dir = NULL; + char user[MAX_USERNAME_LENGTH], fullName[MAX_DESC_LENGTH]; + int nIndex; + + bt_outPacket *outPacket = btRPCPutHeader(BT_CMD_READUSERS, 1, 4); + btRPCPutArg(outPacket, B_INT32_TYPE, &dir, sizeof(int32)); + bt_inPacket *inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket); + if (inPacket) + { + int error, count = 0; + + do + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + memset(user, 0, sizeof(user)); + memset(fullName, 0, sizeof(fullName)); + btRPCGetString(inPacket, user, sizeof(user)); + btRPCGetString(inPacket, fullName, sizeof(fullName)); + + nIndex = m_userList.InsertItem(0, user, 0); + m_userList.SetItemText(nIndex, 1, fullName); + m_userList.SetItemData(nIndex, 0); + } + else break; + } while (++count < 80); + + free(inPacket->buffer); + free(inPacket); + } +} + +void CDomainUsers::AddGroupList() +{ + extern unsigned int authServerIP; + int32 *dir = NULL; + char group[MAX_USERNAME_LENGTH]; + int nIndex; + + bt_outPacket *outPacket = btRPCPutHeader(BT_CMD_READGROUPS, 1, 4); + btRPCPutArg(outPacket, B_INT32_TYPE, &dir, sizeof(int32)); + bt_inPacket *inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket); + if (inPacket) + { + int error, count = 0; + + do + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + memset(group, 0, sizeof(group)); + btRPCGetString(inPacket, group, sizeof(group)); + nIndex = m_userList.InsertItem(0, group, 1); + m_userList.SetItemData(nIndex, 1); + } + else break; + } while (++count < 80); + + free(inPacket->buffer); + free(inPacket); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/DomainUsers.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/DomainUsers.h new file mode 100644 index 0000000000..febcf1fa39 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/DomainUsers.h @@ -0,0 +1,64 @@ +#if !defined(AFX_DOMAINUSERS_H__6F5ED7A2_9C16_11D6_9EF3_00A0C965AF06__INCLUDED_) +#define AFX_DOMAINUSERS_H__6F5ED7A2_9C16_11D6_9EF3_00A0C965AF06__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DomainUsers.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDomainUsers dialog + +class CDomainUsers : public CDialog +{ +// Construction +public: + CDomainUsers(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDomainUsers) + enum { IDD = IDD_DOMAIN_USERS }; + CButton m_okayBtn; + CListCtrl m_userList; + CComboBox m_rights; + //}}AFX_DATA + + int ShowUsers(bool bPrinting); + void AddUserList(); + void AddGroupList(); + + CString GetUser() { return m_user; } + int GetRights() { return m_nRights; } + bool IsGroup() { return m_bGroup; } + void SetPrinting(bool b) { m_bPrinting = b; } + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDomainUsers) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDomainUsers) + virtual BOOL OnInitDialog(); + afx_msg void OnClickDomainUsers(NMHDR* pNMHDR, LRESULT* pResult); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + CImageList m_images; + CString m_user; + int m_nRights; + bool m_bPrinting; + bool m_bGroup; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DOMAINUSERS_H__6F5ED7A2_9C16_11D6_9EF3_00A0C965AF06__INCLUDED_) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.001 b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.001 new file mode 100644 index 0000000000..3e7be83b7e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.001 @@ -0,0 +1,173 @@ +# Microsoft Developer Studio Project File - Name="FileSharing" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=FileSharing - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "FileSharing.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "FileSharing.mak" CFG="FileSharing - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "FileSharing - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "FileSharing - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "FileSharing - Win32 Release" + +# PROP BASE Use_MFC 5 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 5 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_WINDLL" /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /mktyplib203 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386 +# ADD LINK32 /nologo /subsystem:windows /dll /machine:I386 /def:"FileSharing.def" /out:"Release/FileSharing.cpl" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "FileSharing - Win32 Debug" + +# PROP BASE Use_MFC 5 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 5 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_WINDLL" /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /mktyplib203 +# SUBTRACT MTL /nologo +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /def:"FileSharing.def" /out:"Debug/FileSharing.cpl" /implib:"FileSharing.lib" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "FileSharing - Win32 Release" +# Name "FileSharing - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\ctrlpan.cpp +# End Source File +# Begin Source File + +SOURCE=.\FileSharing.cpp +# End Source File +# Begin Source File + +SOURCE=.\FileSharing.rc + +!IF "$(CFG)" == "FileSharing - Win32 Release" + +!ELSEIF "$(CFG)" == "FileSharing - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\scanDlg.cpp +# End Source File +# Begin Source File + +SOURCE=.\scanpan.cpp +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\ctrlpan.h +# End Source File +# Begin Source File + +SOURCE=.\Resource.h +# End Source File +# Begin Source File + +SOURCE=.\FileSharing.h +# End Source File +# Begin Source File + +SOURCE=.\scanDlg.h +# End Source File +# Begin Source File + +SOURCE=.\scanpan.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\res\FileSharing.ico +# End Source File +# Begin Source File + +SOURCE=.\res\FileSharing.rc2 +# End Source File +# End Group +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.cpp new file mode 100644 index 0000000000..f31bf1048e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.cpp @@ -0,0 +1,103 @@ +// FileSharing.cpp : Defines the initialization routines for the DLL. +// + +#include "stdafx.h" +#include "printing.h" +#include "FileSharing.h" +#include "FolderView.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +bt_fileShare_t fileShares[128]; +bt_printer sharedPrinters[BT_MAX_PRINTER_SHARES]; +char authServerName[B_OS_NAME_LENGTH + 1]; +unsigned int authServerIP; + +///////////////////////////////////////////////////////////////////////////// +// CFileSharingApp + +BEGIN_MESSAGE_MAP(CFileSharingApp, CWinApp) + //{{AFX_MSG_MAP(CFileSharingApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFileSharingApp construction + +CFileSharingApp::CFileSharingApp() +{ + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CFileSharingApp object + +CFileSharingApp theApp; + +BOOL CFileSharingApp::InitInstance() +{ + WSADATA wsaData; + AfxEnableControlContainer(); + WSAStartup(MAKEWORD(1, 1), &wsaData); + return CWinApp::InitInstance(); +} + +int CFileSharingApp::ExitInstance() +{ + WSACleanup(); + return CWinApp::ExitInstance(); +} + + +// ----- Library routine for font generation -------------------------------- + +HFONT InitializeControlFont(char *fontName, int fontWeight, int fontSize) +{ + CDC *dc; + HFONT hFnt; + NPLOGFONT plf = (NPLOGFONT) LocalAlloc(LPTR, sizeof(LOGFONT)); + + dc = CWnd::GetDesktopWindow()->GetDC(); + + plf->lfHeight = -MulDiv(fontSize, dc->GetDeviceCaps(LOGPIXELSY), 72); + plf->lfWeight = fontWeight; + lstrcpy((LPSTR) plf->lfFaceName, fontName); + hFnt = CreateFontIndirect(plf); + LocalFree((LOCALHANDLE) plf); + + CWnd::GetDesktopWindow()->ReleaseDC(dc); + return (hFnt); +} + +// GetSelectedListItem() +// +int GetSelectedListItem(CListCtrl *pListCtrl) +{ + int i; + + // Find the first selected document in the list. + for (i = 0; i < pListCtrl->GetItemCount(); i++) + if (pListCtrl->GetItemState(i, LVIS_SELECTED) != 0) + break; + + // If none could be found, what are we doing here? + if (i >= pListCtrl->GetItemCount()) + i = -1; + + return (i); +} + +// PrintString() +// +void PrintString(FILE *fp, const char *str) +{ + if (strchr(str, ' ')) + fprintf(fp, "\"%s\"", str); + else + fprintf(fp, "%s", str); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.def b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.def new file mode 100644 index 0000000000..5305ae9a87 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.def @@ -0,0 +1,7 @@ +; FileSharing.def : Declares the module parameters for the DLL. + +LIBRARY FileSharing + +EXPORTS + ; Explicit exports can go here + CPlApplet diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.exp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.exp new file mode 100644 index 0000000000..1bf7a39be0 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.exp differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.h new file mode 100644 index 0000000000..0bf461426e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.h @@ -0,0 +1,72 @@ +// scanDlg.h : header file +// + +#if !defined(AFX_FileSharing_H__INCLUDED_) +#define AFX_FileSharing_H__INCLUDED_ + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif +#ifdef IDC_STATIC +#undef IDC_STATIC +#endif +#include "resource.h" +#include "ScanPan.h" +#include "FileSharingDlg.h" + +#ifndef _BETALK_H_ +#include "beCompat.h" +#include "betalk.h" +#endif + + +#define iswhite(c) ((c)==' ' || (c)=='\t') + +#define BT_MAX_FILE_SHARES 128 +#define BT_MAX_PRINTER_SHARES 16 + +typedef struct fileShare +{ + char path[B_PATH_NAME_LENGTH]; + char name[B_FILE_NAME_LENGTH]; + bool used; + bool readOnly; + bool followLinks; + bt_user_rights *rights; + int security; + struct fileShare *next; +} bt_fileShare_t; + +HFONT InitializeControlFont(char *fontName, int fontWeight, int fontSize); +int GetSelectedListItem(CListCtrl *pListCtrl); +void PrintString(FILE *fp, const char *str); + +///////////////////////////////////////////////////////////////////////////// +// CFileSharingApp +// See FileSharing.cpp for the implementation of this class +// + +class CFileSharingApp : public CWinApp +{ +public: + CFileSharingApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFileSharingApp) + //}}AFX_VIRTUAL + + //{{AFX_MSG(CFileSharingApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + CScanPanel m_Control; + virtual BOOL InitInstance(); + virtual int ExitInstance(); +}; + +///////////////////////////////////////////////////////////////////////////// + +#endif // !defined(AFX_SCANDLG_H__INCLUDED_) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.plg b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.plg new file mode 100644 index 0000000000..eab45acd8c --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.plg @@ -0,0 +1,42 @@ + + +
+

Build Log

+

+--------------------Configuration: scanappl - Win32 Release-------------------- +

+

Command Lines

+Creating command line "rc.exe /l 0x409 /fo"Release/scanappl.res" /d "NDEBUG" "D:\PROJECTS\scanappl\scanappl.rc"" +Creating temporary file "C:\WINDOWS\TEMP\RSP4355.TMP" with contents +[ +/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_WINDLL" /Fp"Release/scanappl.pch" /Yu"stdafx.h" /Fo"Release/" /Fd"Release/" /FD /c +"D:\PROJECTS\scanappl\scanDlg.cpp" +] +Creating command line "cl.exe @C:\WINDOWS\TEMP\RSP4355.TMP" +Creating temporary file "C:\WINDOWS\TEMP\RSP4356.TMP" with contents +[ +/nologo /subsystem:windows /dll /incremental:no /pdb:"Release/scanappl.pdb" /machine:I386 /def:"scanappl.def" /out:"Release/scanappl.cpl" /implib:"Release/scanappl.lib" +.\Release\ctrlpan.obj +.\Release\scanappl.obj +.\Release\scanDlg.obj +.\Release\scanpan.obj +.\Release\StdAfx.obj +.\Release\scanappl.res +] +Creating command line "link.exe @C:\WINDOWS\TEMP\RSP4356.TMP" +

Output Window

+Compiling resources... +Compiling... +scanDlg.cpp +Linking... + Creating library Release/scanappl.lib and object Release/scanappl.exp +LINK : warning LNK4089: all references to "SHELL32.dll" discarded by /OPT:REF +LINK : warning LNK4089: all references to "comdlg32.dll" discarded by /OPT:REF + + + +

Results

+scanappl.cpl - 0 error(s), 2 warning(s) +
+ + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.rc b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.rc new file mode 100644 index 0000000000..4db7ef4b9b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.rc @@ -0,0 +1,466 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif\r\n" + "#include ""res\\scanappl.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "res\\FileSharing.ico" +IDI_GLOBE ICON "res\\idi_globe.ico" +IDI_LIGHTBULB ICON "res\\lightbulb.ico" +IDI_OPTIONS ICON "res\\options.ico" +IDI_PADLOCK ICON "res\\padlock.ico" +IDI_SHARING ICON "res\\sharing.ico" +IDI_VOLUME ICON "res\\icon1.ico" +IDI_PRINTER ICON "res\\printer.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DOMAIN_USERS DIALOG 70, 20, 258, 229 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Domain Users" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,147,208,50,14,WS_DISABLED + PUSHBUTTON "Cancel",IDCANCEL,201,208,50,14 + LTEXT "Select a user or group from the list below, select the desired access rights, then click the OK button. Click the Cancel button to abort the selection.", + IDC_STATIC,7,7,244,19 + CONTROL "List1",IDC_DOMAIN_USERS,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | + WS_BORDER | WS_TABSTOP,7,31,244,119 + COMBOBOX IDC_DOMAIN_RIGHTS,61,155,98,61,CBS_DROPDOWNLIST | + CBS_SORT | WS_DISABLED | WS_VSCROLL | WS_TABSTOP + LTEXT "Access Rights:",IDC_STATIC,7,157,48,8 + ICON IDI_LIGHTBULB,IDC_STATIC,9,177,20,20 + LTEXT "When granting write access to a shared volume, you are by definition also granting the ability to rename and delete files.", + IDC_STATIC,37,178,216,19 +END + +IDD_FILESHARING_DIALOG DIALOGEX 0, 0, 320, 252 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "File Sharing" +FONT 8, "Tahoma", 0, 0, 0x1 +BEGIN + CONTROL "List1",IDC_SHARE_LIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | + WS_BORDER | WS_TABSTOP,7,67,306,149 + LTEXT "File Sharing Preferences",IDC_MAIN_HEADING,40,7,116,8 + LTEXT "Normally, remote BeOS computers on your network do not have access to files on this computer. You grant them access by explicitly sharing specific folders.", + IDC_STATIC,39,17,256,18 + PUSHBUTTON "&New",IDC_SHARE_NEW,7,49,50,14 + PUSHBUTTON "&Edit",IDC_SHARE_EDIT,61,49,50,14 + PUSHBUTTON "&Remove",IDC_SHARE_REMOVE,115,49,50,14 + LTEXT "Save your changes to file sharing preferences by clicking the OK button. This will not have an effect on users until you manually restart the BeServed file serving application.", + IDC_STATIC,7,221,306,19 + ICON IDI_SHARING,IDC_STATIC,9,8,20,20 + PUSHBUTTON "Se&curity",IDC_SECURITY,263,49,50,14 +END + +IDD_SECURITY DIALOG 0, 0, 248, 106 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Security" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,136,85,50,14 + PUSHBUTTON "Cancel",IDCANCEL,191,85,50,14 + LTEXT "When users connect to this computer to access shared files, the settings here will be used to determine how those users are authenticated.", + IDC_STATIC,39,7,202,29 + LTEXT "Authentication Method:",IDC_STATIC,7,44,76,8 + LTEXT "Server Name:",IDC_STATIC,7,60,45,8 + COMBOBOX IDC_SECURITY_TYPE,92,41,149,50,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_SECURITY_SERVER,92,57,149,14,ES_AUTOHSCROLL | + WS_DISABLED + ICON IDI_PADLOCK,IDC_STATIC,10,8,20,20 +END + +IDD_SHARE_PROPERTIES DIALOG 35, 5, 303, 292 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Sample Share" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,192,271,50,14,WS_DISABLED + PUSHBUTTON "Cancel",IDCANCEL,246,271,50,14 + LTEXT "Sample Share",IDC_SHARE_HEADING,35,7,254,8 + LTEXT "Use this properties window to define the parameters under which you will allow users to share files on this computer.", + IDC_STATIC,36,18,260,18 + EDITTEXT IDC_SHARE_NAME,35,44,116,14,ES_AUTOHSCROLL + LTEXT "Name:",IDC_STATIC,7,47,22,8 + LTEXT "Path:",IDC_STATIC,7,64,18,8 + EDITTEXT IDC_SHARE_PATH,35,61,205,14,ES_AUTOHSCROLL + PUSHBUTTON "&Browse...",IDC_SHARE_BROWSE,246,61,50,14 + CONTROL "Users can make changes to files and folders", + IDC_SHARE_WRITE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7, + 117,156,10 + CONTROL "Follow links leading outside the path",IDC_SHARE_LINKS, + "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,7, + 130,131,10 + ICON IDI_VOLUME,IDC_STATIC,7,7,20,20 + ICON IDI_OPTIONS,IDC_STATIC,7,91,20,20 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,83,289,1 + LTEXT "General Options",IDC_OPTIONS_HEADING,35,96,261,8 + ICON IDI_GLOBE,IDC_STATIC,9,154,20,20 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,149,288,1 + LTEXT "Domain User Access",IDC_DOMAIN_HEADING,35,159,261,8 + CONTROL "List1",IDC_DOMAIN_USERS,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SORTASCENDING | WS_BORDER | + WS_TABSTOP,7,178,234,83 + PUSHBUTTON "&Add",IDC_SHARE_ADD,246,178,50,14 + PUSHBUTTON "&Remove",IDC_SHARE_REMOVE,246,195,50,14,WS_DISABLED +END + +IDD_BROWSER DIALOGEX 0, 0, 210, 167 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select Folder" +FONT 8, "Tahoma", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,101,146,50,14 + PUSHBUTTON "Cancel",IDCANCEL,156,146,50,14 + CONTROL "",IDC_FOLDERVIEW,"{FBF52F2D-9B93-11D2-B482-0020AFD69DE6}", + WS_TABSTOP,4,2,202,139 +END + +IDD_MAINPANEL DIALOGEX 0, 0, 344, 249 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "BeServed File and Print Services" +FONT 8, "Tahoma", 400, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,233,228,50,14 + PUSHBUTTON "Cancel",IDCANCEL,287,228,50,14 +END + +IDD_MANAGE_QUEUE DIALOG 35, 40, 356, 201 +STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_THICKFRAME +CAPTION "Manage Print Queue" +FONT 8, "Tahoma" +BEGIN + PUSHBUTTON "Close",IDCANCEL,298,180,50,14 + CONTROL "List1",IDC_QUEUE_LIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | + WS_TABSTOP,0,0,356,175 + PUSHBUTTON "&Remove",IDC_REMOVE_JOB,241,180,52,14 + PUSHBUTTON "&Pause",IDC_PAUSE_JOB,187,180,50,14 +END + +IDD_PRINTER_PROPERTIES DIALOGEX 45, 5, 303, 332 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Sample Printer" +FONT 8, "Tahoma", 0, 0, 0x0 +BEGIN + LTEXT "Name:",IDC_STATIC,7,47,22,8 + EDITTEXT IDC_PRINTER_NAME,40,44,116,14,ES_AUTOHSCROLL + LTEXT "Device:",IDC_STATIC,7,64,25,8 + COMBOBOX IDC_PRINTER_DEVICE,40,61,200,82,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Type:",IDC_STATIC,7,79,20,8 + COMBOBOX IDC_PRINTER_TYPE,40,76,155,65,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Model:",IDC_STATIC,7,94,22,8 + COMBOBOX IDC_PRINTER_MODEL,40,91,155,99,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Queue:",IDC_STATIC,7,147,25,8 + EDITTEXT IDC_QUEUE_PATH,40,143,200,14,ES_AUTOHSCROLL + PUSHBUTTON "&Browse...",IDC_PRINTER_BROWSE,246,143,50,14 + PUSHBUTTON "&Manage Queue",IDC_MANAGE,40,160,71,14 + CONTROL "List1",IDC_DOMAIN_USERS,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SORTASCENDING | WS_BORDER | + WS_TABSTOP,7,210,234,83 + PUSHBUTTON "&Add",IDC_PRINTER_ADD,246,210,50,14 + PUSHBUTTON "&Remove",IDC_PRINTER_REMOVE,246,227,50,14,WS_DISABLED + DEFPUSHBUTTON "OK",IDOK,192,311,50,14 + PUSHBUTTON "Cancel",IDCANCEL,246,311,50,14 + LTEXT "Sample Printer",IDC_PRINTER_HEADING,35,7,254,8 + LTEXT "Use this properties window to define the parameters under which you will allow users to access this printer from this computer.", + IDC_STATIC,36,18,260,18 + ICON IDI_PRINTER,IDC_STATIC,7,7,20,20 + ICON IDI_GLOBE,IDC_STATIC,9,186,20,20 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,181,287,1 + LTEXT "Domain User Access",IDC_DOMAIN_HEADING,35,191,261,8 + LTEXT "You must also specify a location on this computer where documents can be stored in preparation for printing. Since some of these documents may be large, and may be submitted by multiple users, you should select a location with ample storage.", + IDC_STATIC,7,113,289,27 +END + +IDD_PRINTERSHARING_DIALOG DIALOGEX 0, 0, 320, 252 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "Printer Sharing" +FONT 8, "Tahoma", 0, 0, 0x1 +BEGIN + CONTROL "List1",IDC_PRINTERS,"SysListView32",LVS_REPORT | + LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | + WS_TABSTOP,7,67,306,149 + LTEXT "Printer Sharing Preferences",IDC_MAIN_HEADING,40,7,116, + 8 + LTEXT "Normally, remote BeOS computers on your network do not have permission to use printers available from this computer. You may permit others to share the printers you have access to.", + IDC_STATIC,39,17,256,25 + ICON IDI_SHARING,IDC_STATIC,9,8,20,20 + PUSHBUTTON "&New",IDC_NEW_PRINTER,7,49,50,14 + PUSHBUTTON "&Edit",IDC_EDIT_PRINTER,61,49,50,14 + PUSHBUTTON "&Remove",IDC_REMOVE_PRINTER,115,49,50,14 + PUSHBUTTON "Se&curity",IDC_SECURITY,263,49,50,14 + LTEXT "Save your changes to file sharing preferences by clicking the OK button. This will not have an effect on users until you manually restart the BeServed file serving application.", + IDC_STATIC,7,221,306,19 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,4 + PRODUCTVERSION 1,0,0,4 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "BeServed Control Panel Applet" + VALUE "FileVersion", "1, 0, 0, 5" + VALUE "InternalName", "BeServed" + VALUE "LegalCopyright", "Copyright (C) 2001-2003" + VALUE "OriginalFilename", "BeServed.exe" + VALUE "ProductName", "BeServed" + VALUE "ProductVersion", "1, 0, 0, 5" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DOMAIN_USERS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 251 + TOPMARGIN, 7 + BOTTOMMARGIN, 222 + END + + IDD_FILESHARING_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 313 + TOPMARGIN, 7 + BOTTOMMARGIN, 245 + END + + IDD_SECURITY, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 241 + TOPMARGIN, 7 + BOTTOMMARGIN, 99 + END + + IDD_SHARE_PROPERTIES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 296 + TOPMARGIN, 7 + BOTTOMMARGIN, 285 + END + + IDD_BROWSER, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 206 + TOPMARGIN, 2 + BOTTOMMARGIN, 160 + END + + IDD_MAINPANEL, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 337 + TOPMARGIN, 7 + BOTTOMMARGIN, 242 + END + + IDD_MANAGE_QUEUE, DIALOG + BEGIN + BOTTOMMARGIN, 194 + END + + IDD_PRINTER_PROPERTIES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 296 + TOPMARGIN, 7 + BOTTOMMARGIN, 325 + END + + IDD_PRINTERSHARING_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 313 + TOPMARGIN, 7 + BOTTOMMARGIN, 245 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_FILESHARING BITMAP "res\\filesharing.bmp" +IDB_GROUP BITMAP "res\\group.bmp" +IDB_USER BITMAP "res\\user.bmp" +IDB_VOLUME BITMAP "res\\volume.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog Info +// + +IDD_DOMAIN_USERS DLGINIT +BEGIN + IDC_DOMAIN_RIGHTS, 0x403, 10, 0 +0x6552, 0x6461, 0x6f2d, 0x6c6e, 0x0079, + IDC_DOMAIN_RIGHTS, 0x403, 11, 0 +0x6552, 0x6461, 0x772d, 0x6972, 0x6574, "\000" + 0 +END + +IDD_SECURITY DLGINIT +BEGIN + IDC_SECURITY_TYPE, 0x403, 27, 0 +0x6f4e, 0x4120, 0x7475, 0x6568, 0x746e, 0x6369, 0x7461, 0x6f69, 0x206e, +0x6552, 0x7571, 0x7269, 0x6465, "\000" + IDC_SECURITY_TYPE, 0x403, 29, 0 +0x6542, 0x7553, 0x6572, 0x4120, 0x7475, 0x6568, 0x746e, 0x6369, 0x7461, +0x6f69, 0x206e, 0x6553, 0x7672, 0x7265, "\000" + 0 +END + +IDD_BROWSER DLGINIT +BEGIN + IDC_FOLDERVIEW, 0x376, 150, 0 +0x0008, 0x0000, 0x0031, 0x0039, 0x0039, 0x0039, 0x0030, 0x0037, 0x0037, +0x0030, 0x0300, 0x0000, 0x1f51, 0x0000, 0x175c, 0x0000, 0x0003, 0x0001, +0x0000, 0x0003, 0x0000, 0x0000, 0x0013, 0x0009, 0x8000, 0x0013, 0x0000, +0x0000, 0x000b, 0xffff, 0x000b, 0xffff, 0x000b, 0x0000, 0x000b, 0xffff, +0x000b, 0x0000, 0x000b, 0x0000, 0x000b, 0xffff, 0x000b, 0xffff, 0x000b, +0x0000, 0x000b, 0xffff, 0x0009, 0x5203, 0x0be3, 0x8f91, 0x11ce, 0xe39d, +0xaa00, 0x4b00, 0x51b8, 0x0001, 0x0000, 0x0190, 0x4244, 0x0001, 0x4105, +0x6972, 0x6c61, 0x000b, 0xffff, 0x000b, 0xffff, 0x0008, 0x0002, 0x0000, +0x0000, 0x000b, 0x0000, + 0 +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif +#include "res\scanappl.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.sln b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.sln new file mode 100644 index 0000000000..722eb4ec2e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.sln @@ -0,0 +1,23 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileSharing", "FileSharing.vcproj", "{E318D966-15D7-4FBD-9F7D-8F42974F645D}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = Debug + ConfigName.1 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {E318D966-15D7-4FBD-9F7D-8F42974F645D}.Debug.ActiveCfg = Debug|Win32 + {E318D966-15D7-4FBD-9F7D-8F42974F645D}.Debug.Build.0 = Debug|Win32 + {E318D966-15D7-4FBD-9F7D-8F42974F645D}.Release.ActiveCfg = Release|Win32 + {E318D966-15D7-4FBD-9F7D-8F42974F645D}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionItems) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.suo b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.suo new file mode 100644 index 0000000000..a1d2e5f3c9 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.suo differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.vcproj b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.vcproj new file mode 100644 index 0000000000..6c4612dbc3 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharing.vcproj @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharingDlg.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharingDlg.cpp new file mode 100644 index 0000000000..adbd94e81e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharingDlg.cpp @@ -0,0 +1,727 @@ +// FileSharingDlg.cpp : implementation file +// + +#include "stdafx.h" + +#include "ctype.h" +#include "sys/types.h" +#include "sys/stat.h" + +#include "becompat.h" +#include "betalk.h" + +#include "FileSharing.h" +#include "FileSharingDlg.h" +#include "ShareProperties.h" +#include "printing.h" +#include "Security.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern bt_fileShare_t fileShares[]; +extern bt_printer sharedPrinters[]; +extern char authServerName[]; +extern unsigned int authServerIP; + +char tokBuffer[MAX_NAME_LENGTH + 1], *tokPtr; + +char *keywords[] = +{ + "share", + "as", + "set", + "read", + "write", + "read-write", + "promiscuous", + "on", + "to", + "authenticate", + "with", + "group", + "printer", + "print", + "is", + "spooled", + "device", + "type", + NULL +}; + + + +///////////////////////////////////////////////////////////////////////////// +// CFileSharingDlg dialog + +CFileSharingDlg::CFileSharingDlg() + : CPropertyPage(CFileSharingDlg::IDD) +{ + //{{AFX_DATA_INIT(CFileSharingDlg) + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void CFileSharingDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CFileSharingDlg) + DDX_Control(pDX, IDC_SHARE_REMOVE, m_removeBtn); + DDX_Control(pDX, IDC_SHARE_EDIT, m_editBtn); + DDX_Control(pDX, IDC_MAIN_HEADING, m_heading); + DDX_Control(pDX, IDC_SHARE_LIST, m_shareList); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CFileSharingDlg, CDialog) + //{{AFX_MSG_MAP(CFileSharingDlg) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_NOTIFY(NM_CLICK, IDC_SHARE_LIST, OnClickShareList) + ON_NOTIFY(NM_DBLCLK, IDC_SHARE_LIST, OnDblclkShareList) + ON_BN_CLICKED(IDC_SHARE_EDIT, OnShareEdit) + ON_BN_CLICKED(IDC_SHARE_REMOVE, OnShareRemove) + ON_BN_CLICKED(IDC_SHARE_NEW, OnShareNew) + ON_BN_CLICKED(IDC_SECURITY, OnSecurity) + //}}AFX_MSG_MAP + ON_WM_DESTROY() +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFileSharingDlg message handlers + +BOOL CFileSharingDlg::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + m_editBtn.EnableWindow(FALSE); + m_removeBtn.EnableWindow(FALSE); + + m_shareList.SetExtendedStyle(LVS_EX_FULLROWSELECT); + m_shareList.InsertColumn(0, "Share Name", LVCFMT_LEFT, 150); + m_shareList.InsertColumn(1, "Access", LVCFMT_LEFT, 80); + m_shareList.InsertColumn(2, "Path", LVCFMT_LEFT, 200); + + CBitmap fileShare; + fileShare.LoadBitmap(IDB_VOLUME); + + m_images.Create(16, 16, FALSE, 2, 0); + m_images.Add(&fileShare, (COLORREF) 0); + m_shareList.SetImageList(&m_images, LVSIL_SMALL); + + m_hBoldFont = InitializeControlFont("Tahoma", FW_BOLD, 8); + m_heading.SendMessage(WM_SETFONT, (WPARAM) m_hBoldFont, MAKELPARAM(TRUE, 0)); + + InitShares(); + ListShares(); + + return TRUE; +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CFileSharingDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CFileSharingDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +// InitShares() +// +void CFileSharingDlg::InitShares() +{ + extern char settingsFile[]; + FILE *fp; + char buffer[512]; + int i, length; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + { + fileShares[i].name[0] = 0; + fileShares[i].path[0] = 0; + fileShares[i].used = false; + fileShares[i].readOnly = true; + fileShares[i].followLinks = false; + fileShares[i].next = NULL; + } + + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + { + sharedPrinters[i].printerName[0] = 0; + sharedPrinters[i].deviceName[0] = 0; + sharedPrinters[i].spoolDir[0] = 0; + sharedPrinters[i].rights = NULL; + sharedPrinters[i].security = BT_AUTH_NONE; + sharedPrinters[i].used = false; + sharedPrinters[i].killed = false; + } + + GetCurrentDirectory(sizeof(buffer), buffer); + fp = fopen(settingsFile, "r"); + if (fp) + { + while (fgets(buffer, sizeof(buffer) - 1, fp)) + { + length = strlen(buffer); + if (length <= 1 || buffer[0] == '#') + continue; + + if (buffer[length - 1] == '\n') + buffer[--length] = 0; + + if (strncmp(buffer, "share ", 6) == 0) + GetFileShare(buffer); + else if (strncmp(buffer, "set ", 4) == 0) + GetShareProperty(buffer); + else if (strncmp(buffer, "grant ", 6) == 0) + GetGrant(buffer); + else if (strncmp(buffer, "authenticate ", 13) == 0) + GetAuthenticate(buffer); + else if (strncmp(buffer, "printer ", 8) == 0) + GetPrinter(buffer); + } + + fclose(fp); + } +} + +// GetFileShare() +// +void CFileSharingDlg::GetFileShare(const char *buffer) +{ +// struct stat st; + char path[B_PATH_NAME_LENGTH], share[MAX_NAME_LENGTH + 1], *folder; + int i, tok; + + // Skip over SHARE command. + tokPtr = (char *) buffer + (6 * sizeof(char)); + + tok = GetToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(path, tokBuffer); + tok = GetToken(); + if (tok != BT_TOKEN_AS) + return; + + tok = GetToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + + // Now verify that the share name specified has not already been + // used to share another path. + folder = GetSharePath(share); + if (folder) + return; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (!fileShares[i].used) + { + strcpy(fileShares[i].name, share); + strcpy(fileShares[i].path, path); + fileShares[i].used = true; + return; + } +} + +void CFileSharingDlg::GetShareProperty(const char *buffer) +{ + char share[B_FILE_NAME_LENGTH + 1]; + int tok, shareId; + + // Skip over SET command. + tokPtr = (char *) buffer + (4 * sizeof(char)); + + tok = GetToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + + // Get the index of the share referred to. If the named share cannot be + // found, then abort. + shareId = GetShareId(share); + if (shareId < 0) + return; + + tok = GetToken(); + if (tok == BT_TOKEN_READWRITE) + fileShares[shareId].readOnly = false; +} + +void CFileSharingDlg::GetGrant(const char *buffer) +{ + char share[MAX_NAME_LENGTH + 1]; + int tok, rights; + bool isGroup = false; + + // Skip over GRANT command. + tokPtr = (char *) buffer + (6 * sizeof(char)); + rights = 0; + + do + { + tok = GetToken(); + if (tok == BT_TOKEN_READ) + { + rights |= BT_RIGHTS_READ; + tok = GetToken(); + } + else if (tok == BT_TOKEN_WRITE) + { + rights |= BT_RIGHTS_WRITE; + tok = GetToken(); + } + else if (tok == BT_TOKEN_PRINT) + { + rights |= BT_RIGHTS_PRINT; + tok = GetToken(); + } + } while (tok == BT_TOKEN_COMMA); + + if (tok != BT_TOKEN_ON) + return; + + tok = GetToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + tok = GetToken(); + if (tok != BT_TOKEN_TO) + return; + + tok = GetToken(); + if (tok == BT_TOKEN_GROUP) + { + isGroup = true; + tok = GetToken(); + } + + if (tok != BT_TOKEN_STRING) + return; + + AddUserRights(share, tokBuffer, rights, isGroup); +} + +void CFileSharingDlg::GetAuthenticate(const char *buffer) +{ + struct hostent *ent; + int i, tok; + + // Skip over AUTHENTICATE command. + tokPtr = (char *) buffer + (13 * sizeof(char)); + + tok = GetToken(); + if (tok != BT_TOKEN_WITH) + return; + + tok = GetToken(); + if (tok != BT_TOKEN_STRING) + return; + + // Look up address for given host. + strcpy(authServerName, tokBuffer); + ent = gethostbyname(tokBuffer); + if (ent != NULL) + authServerIP = ntohl(*((unsigned int *) ent->h_addr)); + else + authServerIP = 0; + + // Make all file shares use BeSure authentication. + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + fileShares[i].security = BT_AUTH_BESURE; + + // Make all shared printers use BeSure authentication. + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + sharedPrinters[i].security = BT_AUTH_BESURE; +} + +void CFileSharingDlg::AddUserRights(char *share, char *user, int rights, bool isGroup) +{ + bt_user_rights *ur; + bt_printer *printer = NULL; + int shareId = -1; + + // Now make sure that the rights make sense. If we're granting the + // right to print, we should not have granted the right to read or write. + // We should also be working exclusively with a printer. + if (rights & BT_RIGHTS_PRINT) + { + if ((rights & BT_RIGHTS_READ) == 0 && (rights & BT_RIGHTS_WRITE) == 0) + printer = btFindPrinter(share); + } + else + shareId = GetShareId(share); + + // If we didn't find a printer or a file share, then quit here. + if (!printer && shareId < 0) + return; + + ur = (bt_user_rights *) malloc(sizeof(bt_user_rights)); + if (ur) + { + ur->user = (char *) malloc(strlen(user) + 1); + if (ur->user) + { + strcpy(ur->user, user); + ur->rights = rights; + ur->isGroup = isGroup; + + if (printer) + { + ur->next = printer->rights; + printer->rights = ur; + } + else + { + ur->next = fileShares[shareId].rights; + fileShares[shareId].rights = ur; + } + } + else + free(ur); + } +} + +void CFileSharingDlg::GetPrinter(const char *buffer) +{ + bt_printer printer; + int i, tok; + + // Skip over PRINTER command. + tokPtr = (char *) buffer + (8 * sizeof(char)); + + // Now get the name this printer will be shared as. + tok = GetToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(printer.printerName, tokBuffer); + + // Bypass the IS and TYPE keywords. + tok = GetToken(); + if (tok != BT_TOKEN_IS) + return; + + tok = GetToken(); + if (tok != BT_TOKEN_TYPE) + return; + + // Get the device type of the printer. + tok = GetToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(printer.deviceType, tokBuffer); + + // Bypass the DEVICE keyword. + tok = GetToken(); + if (tok != BT_TOKEN_DEVICE) + return; + + // Get the system device name of the printer. + tok = GetToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(printer.deviceName, tokBuffer); + + // Bypass the SPOOLED TO keywords. + tok = GetToken(); + if (tok != BT_TOKEN_SPOOLED) + return; + + tok = GetToken(); + if (tok != BT_TOKEN_TO) + return; + + // Get the spooling folder, where temporary files will be stored. + tok = GetToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(printer.spoolDir, tokBuffer); + + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + if (!sharedPrinters[i].used) + { + sharedPrinters[i].used = true; + strcpy(sharedPrinters[i].printerName, printer.printerName); + strcpy(sharedPrinters[i].deviceType, printer.deviceType); + strcpy(sharedPrinters[i].deviceName, printer.deviceName); + strcpy(sharedPrinters[i].spoolDir, printer.spoolDir); + break; + } +} + +int CFileSharingDlg::GetToken() +{ + bool quoted = false; + + tokBuffer[0] = 0; + while (*tokPtr && iswhite(*tokPtr)) + tokPtr++; + + if (*tokPtr == ',') + { + *tokPtr++; + return BT_TOKEN_COMMA; + } + else if (*tokPtr == '\"') + { + quoted = true; + tokPtr++; + } + + if (isalnum(*tokPtr) || *tokPtr == '\\') + { + int i = 0; + while (isalnum(*tokPtr) || isValid(*tokPtr) || (quoted && *tokPtr == ' ')) + if (i < MAX_NAME_LENGTH) + tokBuffer[i++] = *tokPtr++; + else + tokPtr++; + + tokBuffer[i] = 0; + + if (!quoted) + for (i = 0; keywords[i]; i++) + if (stricmp(tokBuffer, keywords[i]) == 0) + return ++i; + + if (quoted) + if (*tokPtr != '\"') + return BT_TOKEN_ERROR; + else + tokPtr++; + + return BT_TOKEN_STRING; + } + + return BT_TOKEN_ERROR; +} + +char *CFileSharingDlg::GetSharePath(char *shareName) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (stricmp(fileShares[i].name, shareName) == 0) + return fileShares[i].path; + + return NULL; +} + +int CFileSharingDlg::GetShareId(char *shareName) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (stricmp(fileShares[i].name, shareName) == 0) + return i; + + return -1; +} + +// btFindPrinter() +// +bt_printer *CFileSharingDlg::btFindPrinter(char *printerName) +{ + int i; + + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + if (sharedPrinters[i].used) + if (stricmp(printerName, sharedPrinters[i].printerName) == 0) + return &sharedPrinters[i]; + + return NULL; +} + +// WriteShares() +// +void CFileSharingDlg::WriteShares(FILE *fp) +{ + bt_user_rights *ur; + int i; + + if (fp) + { + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + { + fprintf(fp, "share "); + PrintString(fp, fileShares[i].path); + fprintf(fp, " as "); + PrintString(fp, fileShares[i].name); + fputc('\n', fp); + + if (!fileShares[i].readOnly) + { + fprintf(fp, "set "); + PrintString(fp, fileShares[i].name); + fprintf(fp, " read-write\n"); + } + + if (fileShares[i].followLinks) + { + fprintf(fp, "set "); + PrintString(fp, fileShares[i].name); + fprintf(fp, " promiscuous\n"); + } + + for (ur = fileShares[i].rights; ur; ur = ur->next) + { + int rights = ur->rights; + fprintf(fp, "grant "); + + do + { + if (rights & BT_RIGHTS_READ) + { + fprintf(fp, "read"); + rights &= ~BT_RIGHTS_READ; + } + else if (rights & BT_RIGHTS_WRITE) + { + fprintf(fp, "write"); + rights &= ~BT_RIGHTS_WRITE; + } + + fprintf(fp, "%c", rights > 0 ? ',' : ' '); + } while (rights > 0); + + fprintf(fp, "on "); + PrintString(fp, fileShares[i].name); + fprintf(fp, " to "); + if (ur->isGroup) + fprintf(fp, "group "); + fprintf(fp, "%s\n", ur->user); + } + } + } +} + +// ListShares() +// +void CFileSharingDlg::ListShares() +{ + struct stat st; + int i, nItem; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + { + nItem = m_shareList.InsertItem(0, fileShares[i].name, 0); + m_shareList.SetItemText(nItem, 1, fileShares[i].readOnly ? "Read-only" : "Read-Write"); + m_shareList.SetItemText(nItem, 2, stat(fileShares[i].path, &st) == 0 ? fileShares[i].path : "--- Invalid Path ---"); + m_shareList.SetItemData(nItem, i); + } +} + +void CFileSharingDlg::OnClickShareList(NMHDR* pNMHDR, LRESULT* pResult) +{ + *pResult = 0; + m_editBtn.EnableWindow(GetSelectedListItem(&m_shareList) != -1); + m_removeBtn.EnableWindow(GetSelectedListItem(&m_shareList) != -1); +} + +void CFileSharingDlg::OnDblclkShareList(NMHDR* pNMHDR, LRESULT* pResult) +{ + *pResult = 0; + OnShareEdit(); +} + +void CFileSharingDlg::OnShareEdit() +{ + CShareProperties share; + int nItem = GetSelectedListItem(&m_shareList); + if (nItem != -1) + if (share.ShowProperties(m_shareList.GetItemData(nItem)) == IDOK) + RefreshShare(nItem); +} + +void CFileSharingDlg::OnShareRemove() +{ + int nItem = GetSelectedListItem(&m_shareList); + if (nItem >= 0) + if (MessageBox(WARN_REMOVE_SHARE, fileShares[nItem].name, MB_YESNO | MB_ICONQUESTION) == IDYES) + { + fileShares[nItem].used = false; + m_shareList.DeleteItem(nItem); + } +} + +void CFileSharingDlg::OnShareNew() +{ + CShareProperties share; + int nIndex = m_shareList.GetItemCount(); + strcpy(fileShares[nIndex].name, "Untitled"); + strcpy(fileShares[nIndex].path, "c:\\temp"); + fileShares[nIndex].readOnly = true; + fileShares[nIndex].followLinks = false; + if (share.ShowProperties(nIndex) == IDOK) + { + int nItem = m_shareList.InsertItem(0, fileShares[nIndex].name, 0); + m_shareList.SetItemText(nItem, 1, fileShares[nIndex].readOnly ? "Read-only" : "Read-Write"); + m_shareList.SetItemText(nItem, 2, fileShares[nIndex].path); + m_shareList.SetItemData(nItem, nIndex); + fileShares[nIndex].used = true; + } +} + +void CFileSharingDlg::RefreshShare(int nItem) +{ + int nIndex = m_shareList.GetItemData(nItem); + m_shareList.SetItemText(nItem, 0, fileShares[nIndex].name); + m_shareList.SetItemText(nItem, 1, fileShares[nIndex].readOnly ? "Read-only" : "Read-Write"); + m_shareList.SetItemText(nItem, 2, fileShares[nIndex].path); +} + +void CFileSharingDlg::OnSecurity() +{ + CSecurity security; + security.DoModal(); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharingDlg.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharingDlg.h new file mode 100644 index 0000000000..0f0af443df --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/FileSharingDlg.h @@ -0,0 +1,83 @@ +// FileSharingDlg.h : header file +// + +#if !defined(AFX_FILESHARINGDLG_H__AF7E12FC_F583_11D5_90F9_00C04F0972A7__INCLUDED_) +#define AFX_FILESHARINGDLG_H__AF7E12FC_F583_11D5_90F9_00C04F0972A7__INCLUDED_ + +#include "printing.h" + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// CFileSharingDlg dialog + +class CFileSharingDlg : public CPropertyPage +{ +// Construction +public: + CFileSharingDlg(); // standard constructor + + // Public method used to save changes. + void WriteShares(FILE *fp); + +// Dialog Data + //{{AFX_DATA(CFileSharingDlg) + enum { IDD = IDD_FILESHARING_DIALOG }; + CButton m_removeBtn; + CButton m_editBtn; + CStatic m_heading; + CListCtrl m_shareList; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFileSharingDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + HICON m_hIcon; + HFONT m_hBoldFont; + CImageList m_images; + + // Generated message map functions + //{{AFX_MSG(CFileSharingDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnClickShareList(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDblclkShareList(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnShareEdit(); + afx_msg void OnShareRemove(); + afx_msg void OnShareNew(); + afx_msg void OnSave(); + afx_msg void OnDeploy(); + afx_msg void OnSecurity(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + void InitShares(); + void GetFileShare(const char *buffer); + void GetShareProperty(const char *buffer); + void GetGrant(const char *buffer); + void GetAuthenticate(const char *buffer); + void AddUserRights(char *share, char *user, int rights, bool isGroup); + void GetPrinter(const char *buffer); + int GetToken(); + char * GetSharePath(char *shareName); + int GetShareId(char *shareName); + bt_printer *btFindPrinter(char *printerName); + void ListShares(); + void RefreshShare(int nItem); +}; + + +#define WARN_REMOVE_SHARE "Removing this file share will prevent other users on your network from accessing certain files on this computer. Are you sure you want to remove this file share?" + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_FILESHARINGDLG_H__AF7E12FC_F583_11D5_90F9_00C04F0972A7__INCLUDED_) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/MainPanel.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/MainPanel.cpp new file mode 100644 index 0000000000..abd35cd963 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/MainPanel.cpp @@ -0,0 +1,104 @@ +// MainPanel.cpp : implementation file +// + +#include "stdafx.h" +#include "winsvc.h" + +#include "FileSharing.h" +#include "MainPanel.h" + + +#define SERVICE_CONTROL_USER 128 +#define SERVICE_USER_CONTROL_HUP SERVICE_CONTROL_USER + 1 + +char settingsFile[_MAX_PATH]; + + +// CMainPanel dialog + +IMPLEMENT_DYNAMIC(CMainPanel, CPropertySheet) +CMainPanel::CMainPanel(CWnd* pParent /*=NULL*/) + : CPropertySheet("BeServed File and Print Services", pParent), m_filePanel() +{ + AddPage(&m_filePanel); + AddPage(&m_printerPanel); +} + +CMainPanel::~CMainPanel() +{ +} + +void CMainPanel::DoDataExchange(CDataExchange* pDX) +{ + CPropertySheet::DoDataExchange(pDX); +} + + +BEGIN_MESSAGE_MAP(CMainPanel, CPropertySheet) + ON_BN_CLICKED(IDOK, OnBnClickedOk) +END_MESSAGE_MAP() + + +// CMainPanel message handlers + +BOOL CMainPanel::OnInitDialog() +{ + HKEY hRegKey; + DWORD dwType = 0, dwSize; + char *p; + + // Get service executable folder. + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\BeServed", 0, KEY_READ, &hRegKey) == ERROR_SUCCESS) + { + if (RegQueryValueEx(hRegKey, (LPTSTR) "ImagePath", NULL, &dwType, NULL, &dwSize) == ERROR_SUCCESS) + RegQueryValueEx(hRegKey, (LPTSTR) "ImagePath", NULL, &dwType, (LPBYTE) settingsFile, &dwSize); + + RegCloseKey(hRegKey); + } + + if ((p = strrchr(settingsFile, '\\')) != NULL) + *p = 0; + + strcat(settingsFile, "\\BeServed-Settings"); + + BOOL bResult = CPropertySheet::OnInitDialog(); + return bResult; +} + +// OnBnClickedOk() +// +void CMainPanel::OnBnClickedOk() +{ + extern unsigned authServerIP; + extern char authServerName[]; + SC_HANDLE hManager, hService; + SERVICE_STATUS status; + FILE *fp; + + fp = fopen(settingsFile, "w"); + if (fp) + { + if (authServerIP) + fprintf(fp, "authenticate with %s\n", authServerName); + + m_filePanel.WriteShares(fp); + m_printerPanel.WritePrinters(fp); + + fclose(fp); + } + + hManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); + if (hManager) + { + hService = OpenService(hManager, "BeServed", SERVICE_USER_DEFINED_CONTROL); + if (hService) + { + ControlService(hService, SERVICE_USER_CONTROL_HUP, &status); + CloseServiceHandle(hService); + } + + CloseServiceHandle(hManager); + } + + EndDialog(IDOK); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/MainPanel.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/MainPanel.h new file mode 100644 index 0000000000..56a64b5932 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/MainPanel.h @@ -0,0 +1,30 @@ +#pragma once + +#include "FileSharingDlg.h" +#include "PrinterSharingDlg.h" + +// CMainPanel property sheet + +class CMainPanel : public CPropertySheet +{ + DECLARE_DYNAMIC(CMainPanel) + +public: + CMainPanel(CWnd* pParent = NULL); // standard constructor + virtual ~CMainPanel(); + +// Dialog Data + enum { IDD = IDD_MAINPANEL }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() + + CFileSharingDlg m_filePanel; + CPrinterSharingDlg m_printerPanel; + +public: + virtual BOOL OnInitDialog(); + afx_msg void OnBnClickedOk(); +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ManageQueue.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ManageQueue.cpp new file mode 100644 index 0000000000..927d36769a --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ManageQueue.cpp @@ -0,0 +1,222 @@ +// ManageQueue.cpp : implementation file +// + +#include "stdafx.h" + +#include "FileSharing.h" +#include "ManageQueue.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CManageQueue dialog + + +CManageQueue::CManageQueue(CWnd* pParent /*=NULL*/) + : CDialog(CManageQueue::IDD, pParent) +{ + //{{AFX_DATA_INIT(CManageQueue) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CManageQueue::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CManageQueue) + DDX_Control(pDX, IDC_PAUSE_JOB, m_pauseBtn); + DDX_Control(pDX, IDC_REMOVE_JOB, m_removeBtn); + DDX_Control(pDX, IDC_QUEUE_LIST, m_queue); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CManageQueue, CDialog) + //{{AFX_MSG_MAP(CManageQueue) + ON_WM_TIMER() + ON_NOTIFY(NM_CLICK, IDC_QUEUE_LIST, OnClickQueueList) + ON_BN_CLICKED(IDC_PAUSE_JOB, OnPauseJob) + ON_BN_CLICKED(IDC_REMOVE_JOB, OnRemoveJob) + ON_WM_DESTROY() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CManageQueue message handlers + +int CManageQueue::ShowQueue(bt_printer *printer) +{ + this->printer = printer; + return DoModal(); +} + +BOOL CManageQueue::OnInitDialog() +{ + CDialog::OnInitDialog(); + SetWindowText(CString(printer->printerName) + " Queue"); + + m_queue.SetExtendedStyle(LVS_EX_FULLROWSELECT); + m_queue.InsertColumn(0, "Document Name", LVCFMT_LEFT, 190); + m_queue.InsertColumn(1, "Status", LVCFMT_LEFT, 90); + m_queue.InsertColumn(2, "Submitted By", LVCFMT_LEFT, 110); + m_queue.InsertColumn(3, "Size", LVCFMT_RIGHT, 70); + m_queue.InsertColumn(4, "Submitted On", LVCFMT_LEFT, 170); + m_queue.InsertColumn(5, "Submitted From", LVCFMT_LEFT, 120); + + BuildJobList(); + return TRUE; +} + +void CManageQueue::OnTimer(UINT nIDEvent) +{ + CDialog::OnTimer(nIDEvent); +} + +void CManageQueue::OnClickQueueList(NMHDR* pNMHDR, LRESULT* pResult) +{ + *pResult = 0; + + int nItem = GetSelectedListItem(&m_queue); + if (nItem != -1) + { + CString status = m_queue.GetItemText(nItem, 1); + if (status == "Paused...") + m_pauseBtn.SetWindowText("&Continue"); + else + m_pauseBtn.SetWindowText("&Pause"); + } +} + +void CManageQueue::OnPauseJob() +{ + int nItem = GetSelectedListItem(&m_queue); + if (nItem != -1) + { + bt_print_job *printJob = (bt_print_job *) m_queue.GetItemData(nItem); + if (printJob) + { + CString status = m_queue.GetItemText(nItem, 1); + if (status == "Paused...") + { + WritePrivateProfileString("PrintJob", "Status", "Scheduling...", printJob->jobFile); + m_queue.SetItemText(nItem, 1, "Scheduling..."); + m_pauseBtn.SetWindowText("&Pause"); + } + else + { + WritePrivateProfileString("PrintJob", "Status", "Paused...", printJob->jobFile); + m_queue.SetItemText(nItem, 1, "Paused..."); + m_pauseBtn.SetWindowText("&Continue"); + } + } + } + + m_queue.SetFocus(); +} + +void CManageQueue::OnRemoveJob() +{ + char dataFile[B_PATH_NAME_LENGTH]; + int nItem = GetSelectedListItem(&m_queue); + if (nItem != -1) + { + bt_print_job *printJob = (bt_print_job *) m_queue.GetItemData(nItem); + if (printJob) + { + GetPrivateProfileString("PrintJob", "DataFile", "", dataFile, sizeof(dataFile), printJob->jobFile); + remove(dataFile); + remove(printJob->jobFile); + } + } +} + +void CManageQueue::OnDestroy() +{ + CDialog::OnDestroy(); + + bt_print_job *job = rootJob, *nextJob; + while (job) + { + nextJob = job->next; + free(job); + job = nextJob; + } +} + +void CManageQueue::BuildJobList() +{ + bt_print_job *job; + struct _finddata_t fileInfo; + char path[B_PATH_NAME_LENGTH]; + long int finder, result; + + rootJob = NULL; + + sprintf(path, "%s\\*.job", printer->spoolDir); + finder = result = _findfirst(path, &fileInfo); + while (result != -1) + { + // Create the fully-qualified path to this print job file, then check + // its status. + sprintf(path, "%s\\%s", printer->spoolDir, fileInfo.name); + job = AddPrintJob(printer, path); + job->next = rootJob; + rootJob = job; + + // Get the next print job. + result = _findnext(finder, &fileInfo); + } +} + +bt_print_job *CManageQueue::AddPrintJob(bt_printer *printer, char *path) +{ + bt_print_job *job; + struct stat st; + char dataFile[B_PATH_NAME_LENGTH]; + char buffer[B_FILE_NAME_LENGTH]; + int nItem; + + job = new bt_print_job; + job->next = NULL; + + strcpy(job->jobFile, path); + + GetPrivateProfileString("PrintJob", "JobName", "Untitled", job->jobName, sizeof(job->jobName), path); + nItem = m_queue.InsertItem(0, job->jobName); + m_queue.SetItemData(nItem, (DWORD)(LPVOID) job); + + GetPrivateProfileString("PrintJob", "Status", "", job->status, sizeof(job->status), path); + m_queue.SetItemText(nItem, 1, job->status); + + GetPrivateProfileString("PrintJob", "User", "Unknown", job->sourceUser, sizeof(job->sourceUser), path); + m_queue.SetItemText(nItem, 2, job->sourceUser); + + GetPrivateProfileString("PrintJob", "DataFile", "", buffer, sizeof(buffer), path); + sprintf(dataFile, "%s\\%s", printer->spoolDir, buffer); + if (stat(dataFile, &st) == 0) + { + if (st.st_size > 1024 * 1024) + sprintf(buffer, "%.2f MB", (float) st.st_size / (1024.0 * 1024.0)); + else if (st.st_size > 1024) + sprintf(buffer, "%d KB", st.st_size / 1024); + else + sprintf(buffer, "%d", st.st_size); + + m_queue.SetItemText(nItem, 3, buffer); + + struct tm *time = localtime(&st.st_ctime); + strftime(buffer, sizeof(buffer), "%a %b %d, %Y at %I:%M %p", time); + m_queue.SetItemText(nItem, 4, buffer); + } + + GetPrivateProfileString("PrintJob", "Source", "Unknown", buffer, sizeof(buffer), path); + m_queue.SetItemText(nItem, 5, buffer); + job->sourceAddr = inet_addr(buffer); + + return job; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ManageQueue.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ManageQueue.h new file mode 100644 index 0000000000..350c83d179 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ManageQueue.h @@ -0,0 +1,63 @@ +#if !defined(AFX_MANAGEQUEUE_H__CF35E7B7_4D1E_4FC2_AA9C_5308F6334777__INCLUDED_) +#define AFX_MANAGEQUEUE_H__CF35E7B7_4D1E_4FC2_AA9C_5308F6334777__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "printing.h" + +// ManageQueue.h : header file +// + + +///////////////////////////////////////////////////////////////////////////// +// CManageQueue dialog + +class CManageQueue : public CDialog +{ +// Construction +public: + CManageQueue(CWnd* pParent = NULL); // standard constructor + int ShowQueue(bt_printer *printer); + +// Dialog Data + //{{AFX_DATA(CManageQueue) + enum { IDD = IDD_MANAGE_QUEUE }; + CButton m_pauseBtn; + CButton m_removeBtn; + CListCtrl m_queue; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CManageQueue) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + void BuildJobList(); + bt_print_job *AddPrintJob(bt_printer *printer, char *path); + + bt_printer *printer; + bt_print_job *rootJob; + + // Generated message map functions + //{{AFX_MSG(CManageQueue) + virtual BOOL OnInitDialog(); + afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnClickQueueList(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnPauseJob(); + afx_msg void OnRemoveJob(); + afx_msg void OnDestroy(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MANAGEQUEUE_H__CF35E7B7_4D1E_4FC2_AA9C_5308F6334777__INCLUDED_) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterProperties.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterProperties.cpp new file mode 100644 index 0000000000..57546cdeac --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterProperties.cpp @@ -0,0 +1,296 @@ +// PrinterProperties.cpp : implementation file +// + +#include "stdafx.h" +#include "winspool.h" + +#include "FileSharing.h" +#include "PrinterProperties.h" +#include "BrowseFolders.h" +#include "DomainUsers.h" +#include "ManageQueue.h" +#include "printing.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern bt_printer sharedPrinters[]; +extern unsigned int authServerIP; + + +///////////////////////////////////////////////////////////////////////////// +// CPrinterProperties dialog + + +CPrinterProperties::CPrinterProperties(CWnd* pParent /*=NULL*/) + : CDialog(CPrinterProperties::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPrinterProperties) + m_printerName = _T(""); + m_queuePath = _T(""); + //}}AFX_DATA_INIT +} + + +void CPrinterProperties::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPrinterProperties) + DDX_Control(pDX, IDC_PRINTER_TYPE, m_printerType); + DDX_Control(pDX, IDC_PRINTER_NAME, m_nameCtrl); + DDX_Control(pDX, IDOK, m_okayBtn); + DDX_Control(pDX, IDC_PRINTER_REMOVE, m_removeBtn); + DDX_Control(pDX, IDC_PRINTER_HEADING, m_heading); + DDX_Control(pDX, IDC_DOMAIN_HEADING, m_domainHeading); + DDX_Control(pDX, IDC_PRINTER_DEVICE, m_device); + DDX_Control(pDX, IDC_PRINTER_ADD, m_addBtn); + DDX_Control(pDX, IDC_DOMAIN_USERS, m_userList); + DDX_Text(pDX, IDC_PRINTER_NAME, m_printerName); + DDX_Text(pDX, IDC_QUEUE_PATH, m_queuePath); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_PRINTER_MODEL, m_printerModel); +} + + +BEGIN_MESSAGE_MAP(CPrinterProperties, CDialog) + //{{AFX_MSG_MAP(CPrinterProperties) + ON_NOTIFY(NM_CLICK, IDC_DOMAIN_USERS, OnClickDomainUsers) + ON_BN_CLICKED(IDC_PRINTER_ADD, OnPrinterAdd) + ON_BN_CLICKED(IDC_PRINTER_REMOVE, OnPrinterRemove) + ON_BN_CLICKED(IDC_MANAGE, OnManage) + //}}AFX_MSG_MAP + ON_BN_CLICKED(IDC_PRINTER_BROWSE, OnBnClickedPrinterBrowse) + ON_CBN_SELCHANGE(IDC_PRINTER_TYPE, OnCbnSelchangePrinterType) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPrinterProperties message handlers + +int CPrinterProperties::ShowProperties(int nIndex) +{ + m_nIndex = nIndex; + return DoModal(); +} + +BOOL CPrinterProperties::OnInitDialog() +{ + m_printerName = sharedPrinters[m_nIndex].printerName; + m_queuePath = sharedPrinters[m_nIndex].spoolDir; + + CDialog::OnInitDialog(); + SetWindowText(sharedPrinters[m_nIndex].printerName); + m_heading.SetWindowText(sharedPrinters[m_nIndex].printerName); + + m_hBoldFont = InitializeControlFont("Tahoma", FW_BOLD, 8); + m_heading.SendMessage(WM_SETFONT, (WPARAM) m_hBoldFont, MAKELPARAM(TRUE, 0)); + m_domainHeading.SendMessage(WM_SETFONT, (WPARAM) m_hBoldFont, MAKELPARAM(TRUE, 0)); + + m_userList.SetExtendedStyle(LVS_EX_FULLROWSELECT); + m_userList.InsertColumn(0, "User or Group", LVCFMT_LEFT, 175); + m_userList.InsertColumn(1, "Access", LVCFMT_LEFT, 100); + + m_nameCtrl.SetSel(0, -1); + m_nameCtrl.SetFocus(); + + m_okayBtn.EnableWindow(!m_printerName.IsEmpty() && !m_queuePath.IsEmpty()); + m_addBtn.EnableWindow(authServerIP != 0); + + CBitmap user, group; + user.LoadBitmap(IDB_USER); + group.LoadBitmap(IDB_GROUP); + + m_images.Create(16, 16, FALSE, 2, 0); + m_images.Add(&user, (COLORREF) 0); + m_images.Add(&group, (COLORREF) 0); + m_userList.SetImageList(&m_images, LVSIL_SMALL); + + AddUserList(); + BuildPrinterList(); + m_device.SelectString(-1, sharedPrinters[m_nIndex].deviceName); + + m_printerType.AddString(PRT_TYPE_LASERJET); + m_printerType.AddString(PRT_TYPE_INKJET); + m_printerType.AddString(PRT_TYPE_POSTSCRIPT); + m_printerType.AddString(PRT_TYPE_EPSON_STYLUS); + + if (m_printerType.SelectString(-1, sharedPrinters[m_nIndex].deviceType) == CB_ERR) + m_printerType.SelectString(-1, PRT_TYPE_LASERJET); + + OnCbnSelchangePrinterType(); + return FALSE; +} + +void CPrinterProperties::AddUserList() +{ + bt_user_rights *ur; + int nItem; + + if (sharedPrinters[m_nIndex].security != BT_AUTH_NONE) + for (ur = sharedPrinters[m_nIndex].rights; ur; ur = ur->next) + { + char access[50]; + access[0] = 0; + if (ur->rights & BT_RIGHTS_PRINT) + strcpy(access, "Print"); + + nItem = m_userList.InsertItem(0, ur->user, ur->isGroup ? 1 : 0); + m_userList.SetItemText(nItem, 1, access); + } +} + +void CPrinterProperties::BuildPrinterList() +{ + PRINTER_INFO_1 netPrinters[BT_MAX_PRINTER_SHARES]; + PRINTER_INFO_5 printers[BT_MAX_PRINTER_SHARES]; + DWORD bytesCopied, structsCopied; + int i; + + if (EnumPrinters(PRINTER_ENUM_NAME, NULL, 5, (LPBYTE) printers, sizeof(printers), &bytesCopied, &structsCopied)) + for (i = 0; i < structsCopied; i++) + m_device.AddString(printers[i].pPrinterName); + + if (EnumPrinters(PRINTER_ENUM_CONNECTIONS, NULL, 1, (LPBYTE) netPrinters, sizeof(netPrinters), &bytesCopied, &structsCopied)) + for (i = 0; i < structsCopied; i++) + m_device.AddString(netPrinters[i].pName); +} + +void CPrinterProperties::OnClickDomainUsers(NMHDR* pNMHDR, LRESULT* pResult) +{ + *pResult = 0; + m_removeBtn.EnableWindow(GetSelectedListItem(&m_userList) != -1); +} + +void CPrinterProperties::OnPrinterAdd() +{ + CDomainUsers users; + char access[50]; + int nItem; + + if (users.ShowUsers(true) == IDOK) + { + CString user = users.GetUser(); + int nRights = users.GetRights(); + bool isGroup = users.IsGroup(); + + SaveUserRights(LPCTSTR(user), nRights, isGroup); + + access[0] = 0; + if (nRights & BT_RIGHTS_PRINT) + strcpy(access, "Print"); + + nItem = m_userList.InsertItem(0, user, isGroup ? 1 : 0); + m_userList.SetItemText(nItem, 1, access); + } +} + +void CPrinterProperties::OnPrinterRemove() +{ + bt_user_rights *ur, *lastUR; + int nItem = GetSelectedListItem(&m_userList); + CString user = m_userList.GetItemText(nItem, 0); + + lastUR = NULL; + for (ur = sharedPrinters[m_nIndex].rights; ur; ur = ur->next) + if (strcmp(ur->user, user) == 0) + { + if (lastUR) + lastUR->next = ur->next; + else + sharedPrinters[m_nIndex].rights = ur->next; + + free(ur); + m_userList.DeleteItem(nItem); + break; + } + else + lastUR = ur; +} + +void CPrinterProperties::SaveUserRights(const char *user, int rights, bool isGroup) +{ + bt_user_rights *ur; + + if (user == NULL || rights == 0) + return; + + for (ur = sharedPrinters[m_nIndex].rights; ur; ur = ur->next) + if (strcmp(ur->user, user) == 0) + { + ur->rights = rights; + return; + } + + ur = (bt_user_rights *) malloc(sizeof(bt_user_rights)); + if (ur) + { + ur->user = (char *) malloc(strlen(user) + 1); + if (ur->user) + { + strcpy(ur->user, user); + ur->rights = rights; + ur->isGroup = isGroup; + ur->next = sharedPrinters[m_nIndex].rights; + sharedPrinters[m_nIndex].rights = ur; + } + else + free(ur); + } +} + +void CPrinterProperties::OnOK() +{ + CString itemName; + int item; + + CDialog::OnOK(); + + strcpy(sharedPrinters[m_nIndex].printerName, m_printerName); + strcpy(sharedPrinters[m_nIndex].spoolDir, m_queuePath); + + item = m_device.GetCurSel(); + m_device.GetLBText(item, itemName); + strcpy(sharedPrinters[m_nIndex].deviceName, itemName); + + item = m_printerType.GetCurSel(); + m_printerType.GetLBText(item, itemName); + strcpy(sharedPrinters[m_nIndex].deviceType, itemName); +} + +void CPrinterProperties::OnManage() +{ + CManageQueue queueDlg; + queueDlg.ShowQueue(&sharedPrinters[m_nIndex]); +} + +void CPrinterProperties::OnBnClickedPrinterBrowse() +{ + CBrowseFolders browser; + CWaitCursor wait; + if (browser.SelectFolder(m_queuePath) == IDOK) + { + m_queuePath = browser.GetPath(); + UpdateData(FALSE); + } +} + +void CPrinterProperties::OnCbnSelchangePrinterType() +{ + CString itemName; + int item; + + UpdateData(TRUE); + m_printerModel.ResetContent(); + + item = m_printerType.GetCurSel(); + m_printerType.GetLBText(item, itemName); + if (itemName.CompareNoCase(PRT_TYPE_LASERJET) == 0) + m_printerModel.EnableWindow(FALSE); + else + { + m_printerModel.EnableWindow(TRUE); + + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterProperties.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterProperties.h new file mode 100644 index 0000000000..bde0fcca5d --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterProperties.h @@ -0,0 +1,80 @@ +#include "afxwin.h" +#if !defined(AFX_PRINTERPROPERTIES_H__1ED970A1_8FE9_431D_9F26_5E797DCB8C62__INCLUDED_) +#define AFX_PRINTERPROPERTIES_H__1ED970A1_8FE9_431D_9F26_5E797DCB8C62__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PrinterProperties.h : header file +// + +#define PRT_TYPE_LASERJET "HP LaserJet Compatible" +#define PRT_TYPE_INKJET "HP InkJet Compatible" +#define PRT_TYPE_POSTSCRIPT "Postscript Printer" +#define PRT_TYPE_EPSON_STYLUS "Epson Stylus" + + +///////////////////////////////////////////////////////////////////////////// +// CPrinterProperties dialog + +class CPrinterProperties : public CDialog +{ +// Construction +public: + CPrinterProperties(CWnd* pParent = NULL); // standard constructor + int ShowProperties(int nIndex); + +// Dialog Data + //{{AFX_DATA(CPrinterProperties) + enum { IDD = IDD_PRINTER_PROPERTIES }; + CComboBox m_printerType; + CEdit m_nameCtrl; + CButton m_removeBtn; + CButton m_okayBtn; + CStatic m_heading; + CStatic m_domainHeading; + CComboBox m_device; + CButton m_addBtn; + CListCtrl m_userList; + CString m_printerName; + CString m_queuePath; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPrinterProperties) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + void AddUserList(); + void BuildPrinterList(); + void SaveUserRights(const char *user, int rights, bool isGroup); + + CImageList m_images; + HFONT m_hBoldFont; + int m_nIndex; + + // Generated message map functions + //{{AFX_MSG(CPrinterProperties) + virtual BOOL OnInitDialog(); + afx_msg void OnClickDomainUsers(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnPrinterAdd(); + afx_msg void OnPrinterRemove(); + afx_msg void OnManage(); + afx_msg void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnBnClickedPrinterBrowse(); + afx_msg void OnCbnSelchangePrinterType(); + CComboBox m_printerModel; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PRINTERPROPERTIES_H__1ED970A1_8FE9_431D_9F26_5E797DCB8C62__INCLUDED_) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterSharingDlg.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterSharingDlg.cpp new file mode 100644 index 0000000000..ac57a299df --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterSharingDlg.cpp @@ -0,0 +1,264 @@ +// PrinterSharingDlg.cpp : implementation file +// + +#include "stdafx.h" + +#include "ctype.h" +#include "sys/types.h" +#include "sys/stat.h" + +#include "becompat.h" +#include "betalk.h" + +#include "FileSharing.h" +#include "PrinterSharingDlg.h" +#include "PrinterProperties.h" +#include "printing.h" +#include "Security.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern bt_printer sharedPrinters[]; +extern char authServerName[]; +extern unsigned int authServerIP; + +extern char tokBuffer[MAX_NAME_LENGTH + 1], *tokPtr; +extern char *keywords[]; + + +///////////////////////////////////////////////////////////////////////////// +// CPrinterSharingDlg dialog + +CPrinterSharingDlg::CPrinterSharingDlg() + : CPropertyPage(CPrinterSharingDlg::IDD) +{ + //{{AFX_DATA_INIT(CPrinterSharingDlg) + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void CPrinterSharingDlg::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPrinterSharingDlg) + DDX_Control(pDX, IDC_MAIN_HEADING, m_heading); + DDX_Control(pDX, IDC_PRINTERS, m_printerList); + DDX_Control(pDX, IDC_REMOVE_PRINTER, m_removeBtn); + DDX_Control(pDX, IDC_EDIT_PRINTER, m_editBtn); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CPrinterSharingDlg, CPropertyPage) + //{{AFX_MSG_MAP(CPrinterSharingDlg) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_NOTIFY(NM_CLICK, IDC_PRINTERS, OnClickPrinters) + ON_NOTIFY(NM_DBLCLK, IDC_PRINTERS, OnDblclkPrinters) + ON_BN_CLICKED(IDC_EDIT_PRINTER, OnEditPrinter) + ON_BN_CLICKED(IDC_REMOVE_PRINTER, OnRemovePrinter) + ON_BN_CLICKED(IDC_NEW_PRINTER, OnNewPrinter) + ON_BN_CLICKED(IDC_SECURITY, OnSecurity) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPrinterSharingDlg message handlers + +BOOL CPrinterSharingDlg::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + m_editBtn.EnableWindow(FALSE); + m_removeBtn.EnableWindow(FALSE); + + m_printerList.SetExtendedStyle(LVS_EX_FULLROWSELECT); + m_printerList.InsertColumn(0, "Printer Name", LVCFMT_LEFT, 120); + m_printerList.InsertColumn(1, "Local Device", LVCFMT_LEFT, 120); + m_printerList.InsertColumn(2, "Queue Path", LVCFMT_LEFT, 200); + + CBitmap printer; + printer.LoadBitmap(IDB_USER); + + m_images.Create(16, 16, FALSE, 2, 0); + m_images.Add(&printer, (COLORREF) 0); + m_printerList.SetImageList(&m_images, LVSIL_SMALL); + + m_hBoldFont = InitializeControlFont("Tahoma", FW_BOLD, 8); + m_heading.SendMessage(WM_SETFONT, (WPARAM) m_hBoldFont, MAKELPARAM(TRUE, 0)); + + ListPrinters(); + + return TRUE; +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CPrinterSharingDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CPropertyPage::OnPaint(); + } +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CPrinterSharingDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void CPrinterSharingDlg::OnClickPrinters(NMHDR* pNMHDR, LRESULT* pResult) +{ + *pResult = 0; + m_editBtn.EnableWindow(GetSelectedListItem(&m_printerList) != -1); + m_removeBtn.EnableWindow(GetSelectedListItem(&m_printerList) != -1); +} + +void CPrinterSharingDlg::OnDblclkPrinters(NMHDR* pNMHDR, LRESULT* pResult) +{ + *pResult = 0; + OnEditPrinter(); +} + +void CPrinterSharingDlg::OnEditPrinter() +{ + CPrinterProperties printer; + int nItem = GetSelectedListItem(&m_printerList); + if (nItem != -1) + if (printer.ShowProperties(m_printerList.GetItemData(nItem)) == IDOK) + RefreshPrinter(nItem); +} + +void CPrinterSharingDlg::OnRemovePrinter() +{ + int nItem = GetSelectedListItem(&m_printerList); + if (nItem >= 0) + if (MessageBox(WARN_REMOVE_PRINTER, sharedPrinters[nItem].printerName, MB_YESNO | MB_ICONQUESTION) == IDYES) + { + sharedPrinters[nItem].used = false; + m_printerList.DeleteItem(nItem); + } +} + +void CPrinterSharingDlg::OnNewPrinter() +{ + CPrinterProperties printer; + struct stat st; + int nIndex; + + for (nIndex = 0; nIndex < BT_MAX_PRINTER_SHARES; nIndex++) + if (!sharedPrinters[nIndex].used) + break; + + if (nIndex == BT_MAX_PRINTER_SHARES) + return; + + strcpy(sharedPrinters[nIndex].printerName, "Untitled"); + strcpy(sharedPrinters[nIndex].spoolDir, "c:\\temp"); + if (printer.ShowProperties(nIndex) == IDOK) + { + int nItem = m_printerList.InsertItem(0, sharedPrinters[nIndex].printerName, 0); + m_printerList.SetItemText(nItem, 1, sharedPrinters[nIndex].deviceName); + m_printerList.SetItemText(nItem, 2, stat(sharedPrinters[nIndex].spoolDir, &st) == 0 ? sharedPrinters[nIndex].spoolDir : "--- Invalid Path ---"); + m_printerList.SetItemData(nItem, nIndex); + sharedPrinters[nIndex].used = true; + } +} + +void CPrinterSharingDlg::OnSecurity() +{ + CSecurity security; + security.DoModal(); +} + +// ListPrinters() +// +void CPrinterSharingDlg::ListPrinters() +{ + struct stat st; + int i, nItem; + + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + if (sharedPrinters[i].used) + { + nItem = m_printerList.InsertItem(0, sharedPrinters[i].printerName, 0); + m_printerList.SetItemText(nItem, 1, sharedPrinters[i].deviceName); + m_printerList.SetItemText(nItem, 2, stat(sharedPrinters[i].spoolDir, &st) == 0 ? sharedPrinters[i].spoolDir : "--- Invalid Path ---"); + m_printerList.SetItemData(nItem, i); + } +} + +void CPrinterSharingDlg::RefreshPrinter(int nItem) +{ + struct stat st; + int nIndex = m_printerList.GetItemData(nItem); + m_printerList.SetItemText(nItem, 0, sharedPrinters[nItem].printerName); + m_printerList.SetItemText(nItem, 1, sharedPrinters[nItem].deviceName); + m_printerList.SetItemText(nItem, 2, stat(sharedPrinters[nItem].spoolDir, &st) == 0 ? sharedPrinters[nItem].spoolDir : "--- Invalid Path ---"); +} + +// WritePrinters() +// +void CPrinterSharingDlg::WritePrinters(FILE *fp) +{ + bt_user_rights *ur; + int i; + + if (fp) + { + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + if (sharedPrinters[i].used) + { + fprintf(fp, "printer "); + PrintString(fp, sharedPrinters[i].printerName); + fprintf(fp, " is type "); + PrintString(fp, sharedPrinters[i].deviceType); + fprintf(fp, " device "); + PrintString(fp, sharedPrinters[i].deviceName); + fprintf(fp, " spooled to "); + PrintString(fp, sharedPrinters[i].spoolDir); + fputc('\n', fp); + + for (ur = sharedPrinters[i].rights; ur; ur = ur->next) + if (ur->rights & BT_RIGHTS_PRINT) + { + fprintf(fp, "grant print on "); + PrintString(fp, sharedPrinters[i].printerName); + fprintf(fp, " to "); + if (ur->isGroup) + fprintf(fp, "group "); + fprintf(fp, "%s\n", ur->user); + } + } + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterSharingDlg.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterSharingDlg.h new file mode 100644 index 0000000000..671a136f43 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/PrinterSharingDlg.h @@ -0,0 +1,78 @@ +// PrinterSharingDlg.h : header file +// + +#if !defined(AFX_PRINTERSHARINGDLG_H__2CCAE8D2_2185_42AD_A50D_AEC540DE7434__INCLUDED_) +#define AFX_PRINTERSHARINGDLG_H__2CCAE8D2_2185_42AD_A50D_AEC540DE7434__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +#include "printing.h" + + +///////////////////////////////////////////////////////////////////////////// +// CPrinterSharingDlg dialog + +class CPrinterSharingDlg : public CPropertyPage +{ +// Construction +public: + CPrinterSharingDlg(); // standard constructor + + void WritePrinters(FILE *fp); + +// Dialog Data + //{{AFX_DATA(CPrinterSharingDlg) + enum { IDD = IDD_PRINTERSHARING_DIALOG }; + CStatic m_heading; + CListCtrl m_printerList; + CButton m_removeBtn; + CButton m_editBtn; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPrinterSharingDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + void ListPrinters(); + void RefreshPrinter(int nItem); + + void initPrinters(); + void getGrant(const char *buffer); + void getAuthenticate(const char *buffer); + void addUserRights(char *share, char *user, int rights, bool isGroup); + void getPrinter(const char *buffer); + int getToken(); + bt_printer *btFindPrinter(char *printerName); + + CImageList m_images; + HICON m_hIcon; + HFONT m_hBoldFont; + + // Generated message map functions + //{{AFX_MSG(CPrinterSharingDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnClickPrinters(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDblclkPrinters(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnEditPrinter(); + afx_msg void OnRemovePrinter(); + afx_msg void OnNewPrinter(); + afx_msg void OnSecurity(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#define WARN_REMOVE_PRINTER "Removing this printer will prevent other users on your network from using it. Are you sure you want to remove this printer?" + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PRINTERSHARINGDLG_H__2CCAE8D2_2185_42AD_A50D_AEC540DE7434__INCLUDED_) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/Security.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/Security.cpp new file mode 100644 index 0000000000..43541b7325 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/Security.cpp @@ -0,0 +1,115 @@ +// Security.cpp : implementation file +// + +#include "stdafx.h" +#include "winsock2.h" + +#include "FileSharing.h" +#include "Security.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSecurity dialog + + +CSecurity::CSecurity(CWnd* pParent /*=NULL*/) + : CDialog(CSecurity::IDD, pParent) +{ + //{{AFX_DATA_INIT(CSecurity) + m_server = _T(""); + //}}AFX_DATA_INIT +} + + +void CSecurity::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSecurity) + DDX_Control(pDX, IDOK, m_okayBtn); + DDX_Control(pDX, IDC_SECURITY_TYPE, m_type); + DDX_Control(pDX, IDC_SECURITY_SERVER, m_serverCtrl); + DDX_Text(pDX, IDC_SECURITY_SERVER, m_server); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSecurity, CDialog) + //{{AFX_MSG_MAP(CSecurity) + ON_EN_CHANGE(IDC_SECURITY_SERVER, OnChangeSecurityServer) + ON_CBN_SELCHANGE(IDC_SECURITY_TYPE, OnSelchangeSecurityType) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSecurity message handlers + +BOOL CSecurity::OnInitDialog() +{ + extern char authServerName[]; + extern unsigned int authServerIP; + + CDialog::OnInitDialog(); + + if (authServerIP) + { + m_type.SelectString(-1, "BeSure Authentication Server"); + m_server = authServerName; + UpdateData(FALSE); + m_serverCtrl.EnableWindow(TRUE); + } + else + m_type.SelectString(-1, "No Authentication Required"); + + m_type.SetFocus(); + + return FALSE; +} + +void CSecurity::OnChangeSecurityServer() +{ + UpdateData(TRUE); + m_okayBtn.EnableWindow(!m_server.IsEmpty()); +} + +void CSecurity::OnSelchangeSecurityType() +{ + CString typeName; + int nType = m_type.GetCurSel(); + + m_type.GetLBText(nType, typeName); + if (typeName.CompareNoCase("No Authentication Required") == 0) + { + m_serverCtrl.EnableWindow(FALSE); + m_okayBtn.EnableWindow(TRUE); + } + else + { + m_serverCtrl.EnableWindow(TRUE); + UpdateData(TRUE); + m_okayBtn.EnableWindow(!m_server.IsEmpty()); + } +} + +void CSecurity::OnOK() +{ + extern char authServerName[]; + extern unsigned int authServerIP; + struct hostent *ent; + + CDialog::OnOK(); + + strcpy(authServerName, m_server); + ent = gethostbyname(authServerName); + if (ent == NULL) + { + unsigned long addr = inet_addr(authServerName); + authServerIP = ntohl(addr); + } + else + authServerIP = ntohl(*((unsigned int *) ent->h_addr)); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/Security.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/Security.h new file mode 100644 index 0000000000..58cc47144e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/Security.h @@ -0,0 +1,52 @@ +#if !defined(AFX_SECURITY_H__6F5ED7A3_9C16_11D6_9EF3_00A0C965AF06__INCLUDED_) +#define AFX_SECURITY_H__6F5ED7A3_9C16_11D6_9EF3_00A0C965AF06__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Security.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSecurity dialog + +class CSecurity : public CDialog +{ +// Construction +public: + CSecurity(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CSecurity) + enum { IDD = IDD_SECURITY }; + CButton m_okayBtn; + CComboBox m_type; + CEdit m_serverCtrl; + CString m_server; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSecurity) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CSecurity) + virtual BOOL OnInitDialog(); + afx_msg void OnChangeSecurityServer(); + afx_msg void OnSelchangeSecurityType(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SECURITY_H__6F5ED7A3_9C16_11D6_9EF3_00A0C965AF06__INCLUDED_) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ShareProperties.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ShareProperties.cpp new file mode 100644 index 0000000000..97a1ae4218 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ShareProperties.cpp @@ -0,0 +1,253 @@ +// ShareProperties.cpp : implementation file +// + +#include "stdafx.h" + +#include "FileSharing.h" +#include "ShareProperties.h" +#include "BrowseFolders.h" +#include "DomainUsers.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern bt_fileShare_t fileShares[]; +extern unsigned int authServerIP; + + +///////////////////////////////////////////////////////////////////////////// +// CShareProperties dialog + + +CShareProperties::CShareProperties(CWnd* pParent /*=NULL*/) + : CDialog(CShareProperties::IDD, pParent) +{ + //{{AFX_DATA_INIT(CShareProperties) + m_bLinks = FALSE; + m_bReadWrite = FALSE; + m_shareName = _T(""); + m_sharePath = _T(""); + //}}AFX_DATA_INIT +} + + +void CShareProperties::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CShareProperties) + DDX_Control(pDX, IDC_SHARE_ADD, m_addBtn); + DDX_Control(pDX, IDC_SHARE_REMOVE, m_removeBtn); + DDX_Control(pDX, IDC_DOMAIN_USERS, m_userList); + DDX_Control(pDX, IDC_DOMAIN_HEADING, m_domainHeading); + DDX_Control(pDX, IDC_OPTIONS_HEADING, m_optionsHeading); + DDX_Control(pDX, IDC_SHARE_NAME, m_nameCtrl); + DDX_Control(pDX, IDOK, m_okayBtn); + DDX_Control(pDX, IDC_SHARE_HEADING, m_heading); + DDX_Check(pDX, IDC_SHARE_LINKS, m_bLinks); + DDX_Check(pDX, IDC_SHARE_WRITE, m_bReadWrite); + DDX_Text(pDX, IDC_SHARE_NAME, m_shareName); + DDX_Text(pDX, IDC_SHARE_PATH, m_sharePath); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CShareProperties, CDialog) + //{{AFX_MSG_MAP(CShareProperties) + ON_BN_CLICKED(IDC_SHARE_BROWSE, OnShareBrowse) + ON_EN_CHANGE(IDC_SHARE_NAME, OnChangeShareName) + ON_EN_CHANGE(IDC_SHARE_PATH, OnChangeSharePath) + ON_NOTIFY(NM_CLICK, IDC_DOMAIN_USERS, OnClickDomainUsers) + ON_BN_CLICKED(IDC_SHARE_ADD, OnShareAdd) + ON_BN_CLICKED(IDC_SHARE_REMOVE, OnShareRemove) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CShareProperties message handlers + +BOOL CShareProperties::OnInitDialog() +{ + m_shareName = fileShares[m_nIndex].name; + m_sharePath = fileShares[m_nIndex].path; + m_bReadWrite = !fileShares[m_nIndex].readOnly; + m_bLinks = FALSE; + + CDialog::OnInitDialog(); + SetWindowText(fileShares[m_nIndex].name); + m_heading.SetWindowText(fileShares[m_nIndex].name); + + m_hBoldFont = InitializeControlFont("Tahoma", FW_BOLD, 8); + m_heading.SendMessage(WM_SETFONT, (WPARAM) m_hBoldFont, MAKELPARAM(TRUE, 0)); + m_optionsHeading.SendMessage(WM_SETFONT, (WPARAM) m_hBoldFont, MAKELPARAM(TRUE, 0)); + m_domainHeading.SendMessage(WM_SETFONT, (WPARAM) m_hBoldFont, MAKELPARAM(TRUE, 0)); + + m_userList.SetExtendedStyle(LVS_EX_FULLROWSELECT); + m_userList.InsertColumn(0, "User or Group", LVCFMT_LEFT, 175); + m_userList.InsertColumn(1, "Access", LVCFMT_LEFT, 100); + + m_nameCtrl.SetSel(0, -1); + m_nameCtrl.SetFocus(); + + m_okayBtn.EnableWindow(!m_shareName.IsEmpty() && !m_sharePath.IsEmpty()); + m_addBtn.EnableWindow(authServerIP != 0); + + CBitmap user, group; + user.LoadBitmap(IDB_USER); + group.LoadBitmap(IDB_GROUP); + + m_images.Create(16, 16, FALSE, 2, 0); + m_images.Add(&user, (COLORREF) 0); + m_images.Add(&group, (COLORREF) 0); + m_userList.SetImageList(&m_images, LVSIL_SMALL); + + AddUserList(); + + return FALSE; +} + +void CShareProperties::OnShareBrowse() +{ + CBrowseFolders browser; + CWaitCursor wait; + if (browser.SelectFolder(m_sharePath) == IDOK) + { + m_sharePath = browser.GetPath(); + UpdateData(FALSE); + } +} + +void CShareProperties::OnChangeShareName() +{ + UpdateData(TRUE); + m_okayBtn.EnableWindow(!m_shareName.IsEmpty()); +} + +void CShareProperties::OnChangeSharePath() +{ + UpdateData(TRUE); + m_okayBtn.EnableWindow(!m_sharePath.IsEmpty()); +} + +void CShareProperties::OnOK() +{ + CDialog::OnOK(); + + strcpy(fileShares[m_nIndex].name, m_shareName); + strcpy(fileShares[m_nIndex].path, m_sharePath); + fileShares[m_nIndex].readOnly = !m_bReadWrite; + fileShares[m_nIndex].followLinks = m_bLinks ? 1 : 0; +} + +int CShareProperties::ShowProperties(int nIndex) +{ + m_nIndex = nIndex; + return DoModal(); +} + +void CShareProperties::AddUserList() +{ + bt_user_rights *ur; + int nItem; + + if (fileShares[m_nIndex].security != BT_AUTH_NONE) + for (ur = fileShares[m_nIndex].rights; ur; ur = ur->next) + { + char access[50]; + access[0] = 0; + if (ur->rights & BT_RIGHTS_READ) + strcat(access, "Read "); + if (ur->rights & BT_RIGHTS_WRITE) + strcat(access, "Write"); + + nItem = m_userList.InsertItem(0, ur->user, ur->isGroup ? 1 : 0); + m_userList.SetItemText(nItem, 1, access); + } +} + +void CShareProperties::OnClickDomainUsers(NMHDR* pNMHDR, LRESULT* pResult) +{ + *pResult = 0; + m_removeBtn.EnableWindow(GetSelectedListItem(&m_userList) != -1); +} + +void CShareProperties::OnShareAdd() +{ + CDomainUsers users; + char access[50]; + int nItem; + + if (users.DoModal() == IDOK) + { + CString user = users.GetUser(); + int nRights = users.GetRights(); + bool isGroup = users.IsGroup(); + + SaveUserRights(LPCTSTR(user), nRights, isGroup); + + access[0] = 0; + if (nRights & BT_RIGHTS_READ) + strcat(access, "Read "); + if (nRights & BT_RIGHTS_WRITE) + strcat(access, "Write"); + + nItem = m_userList.InsertItem(0, user, isGroup ? 1 : 0); + m_userList.SetItemText(nItem, 1, access); + } +} + +void CShareProperties::OnShareRemove() +{ + bt_user_rights *ur, *lastUR; + int nItem = GetSelectedListItem(&m_userList); + CString user = m_userList.GetItemText(nItem, 0); + + lastUR = NULL; + for (ur = fileShares[m_nIndex].rights; ur; ur = ur->next) + if (strcmp(ur->user, user) == 0) + { + if (lastUR) + lastUR->next = ur->next; + else + fileShares[m_nIndex].rights = ur->next; + + free(ur); + m_userList.DeleteItem(nItem); + break; + } + else + lastUR = ur; +} + +void CShareProperties::SaveUserRights(const char *user, int rights, bool isGroup) +{ + bt_user_rights *ur; + + if (user == NULL || rights == 0) + return; + + for (ur = fileShares[m_nIndex].rights; ur; ur = ur->next) + if (strcmp(ur->user, user) == 0) + { + ur->rights = rights; + return; + } + + ur = (bt_user_rights *) malloc(sizeof(bt_user_rights)); + if (ur) + { + ur->user = (char *) malloc(strlen(user) + 1); + if (ur->user) + { + strcpy(ur->user, user); + ur->rights = rights; + ur->isGroup = isGroup; + ur->next = fileShares[m_nIndex].rights; + fileShares[m_nIndex].rights = ur; + } + else + free(ur); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ShareProperties.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ShareProperties.h new file mode 100644 index 0000000000..2384d3442b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ShareProperties.h @@ -0,0 +1,73 @@ +#if !defined(AFX_SHAREPROPERTIES_H__AF7E1305_F583_11D5_90F9_00C04F0972A7__INCLUDED_) +#define AFX_SHAREPROPERTIES_H__AF7E1305_F583_11D5_90F9_00C04F0972A7__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ShareProperties.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CShareProperties dialog + +class CShareProperties : public CDialog +{ +// Construction +public: + CShareProperties(CWnd* pParent = NULL); // standard constructor + + int ShowProperties(int nIndex); + +// Dialog Data + //{{AFX_DATA(CShareProperties) + enum { IDD = IDD_SHARE_PROPERTIES }; + CButton m_addBtn; + CButton m_removeBtn; + CListCtrl m_userList; + CStatic m_domainHeading; + CStatic m_optionsHeading; + CEdit m_nameCtrl; + CButton m_okayBtn; + CStatic m_heading; + BOOL m_bLinks; + BOOL m_bReadWrite; + CString m_shareName; + CString m_sharePath; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CShareProperties) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + void AddUserList(); + void SaveUserRights(const char *user, int rights, bool isGroup); + + CImageList m_images; + HFONT m_hBoldFont; + + // Generated message map functions + //{{AFX_MSG(CShareProperties) + virtual BOOL OnInitDialog(); + afx_msg void OnShareBrowse(); + afx_msg void OnChangeShareName(); + afx_msg void OnChangeSharePath(); + virtual void OnOK(); + afx_msg void OnClickDomainUsers(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnShareAdd(); + afx_msg void OnShareRemove(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + int m_nIndex; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SHAREPROPERTIES_H__AF7E1305_F583_11D5_90F9_00C04F0972A7__INCLUDED_) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/StdAfx.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/StdAfx.cpp new file mode 100644 index 0000000000..034fb44683 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/StdAfx.cpp @@ -0,0 +1,6 @@ +// stdafx.cpp : source file that includes just the standard includes +// scanappl.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/StdAfx.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/StdAfx.h new file mode 100644 index 0000000000..a6b03f6e77 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/StdAfx.h @@ -0,0 +1,21 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__INCLUDED_) +#define AFX_STDAFX_H__INCLUDED_ + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC OLE classes +#include // MFC OLE dialog classes +#include // MFC OLE automation classes +#include // MFC database classes +#include // MFC common controls +#include + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__INCLUDED_) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/beCompat.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/beCompat.h new file mode 100644 index 0000000000..aa184c2aa1 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/beCompat.h @@ -0,0 +1,147 @@ +#ifndef B_OK + +#include +#include +//#include +//#include +//#include + +#define B_OK 0 +#define B_ENTRY_NOT_FOUND ENOENT +#define B_PATH_NAME_LENGTH 1024 +#define B_FILE_NAME_LENGTH 256 +#define B_OS_NAME_LENGTH 32 +#define B_INTERRUPTED 1 + +#define BEOS_ENOENT 2147508227 +#define BEOS_EACCES 2147483650 +#define BEOS_ENOMEM 2147483648 +#define BEOS_EINVAL 0 + +#ifndef true +#define true 1 +#define false 0 +#endif + +#define WSTAT_MODE 0x0001 +#define WSTAT_UID 0x0002 +#define WSTAT_GID 0x0004 +#define WSTAT_SIZE 0x0008 +#define WSTAT_ATIME 0x0010 +#define WSTAT_MTIME 0x0020 +#define WSTAT_CRTIME 0x0040 + +#define B_COMMON_SETTINGS_DIRECTORY ".\\" +#define B_COMMON_SYSTEM_DIRECTORY ".\\" + +#define ENOTSUP 1 + +#define B_HOST_TO_LENDIAN_INT32(x) (x) +#define B_HOST_TO_LENDIAN_INT64(x) (x) +#define B_HOST_TO_BENDIAN_INT32(x) (x) +#define B_HOST_TO_BENDIAN_INT64(x) (x) +#define B_LENDIAN_TO_HOST_INT32(x) (x) +#define B_LENDIAN_TO_HOST_INT64(x) (x) +#define B_BENDIAN_TO_HOST_INT32(x) (x) +#define B_BENDIAN_TO_HOST_INT64(x) (x) + +#define lstat(f, s) stat(f, s) +#define S_ISDIR(m) ((m) & _S_IFDIR) + +typedef char int8; +typedef long int32; +typedef LONGLONG int64; +typedef unsigned char uint8; +typedef unsigned long uint32; +typedef ULONGLONG uint64; + +typedef uint64 vnode_id; +typedef uint64 beos_ino_t; +typedef uint64 beos_off_t; +typedef unsigned long beos_dev_t; +typedef long sem_id; +typedef long thread_id; + + +enum { + B_ANY_TYPE = 'ANYT', + B_BOOL_TYPE = 'BOOL', + B_CHAR_TYPE = 'CHAR', + B_COLOR_8_BIT_TYPE = 'CLRB', + B_DOUBLE_TYPE = 'DBLE', + B_FLOAT_TYPE = 'FLOT', + B_GRAYSCALE_8_BIT_TYPE = 'GRYB', + B_INT64_TYPE = 'LLNG', + B_INT32_TYPE = 'LONG', + B_INT16_TYPE = 'SHRT', + B_INT8_TYPE = 'BYTE', + B_MESSAGE_TYPE = 'MSGG', + B_MESSENGER_TYPE = 'MSNG', + B_MIME_TYPE = 'MIME', + B_MONOCHROME_1_BIT_TYPE = 'MNOB', + B_OBJECT_TYPE = 'OPTR', + B_OFF_T_TYPE = 'OFFT', + B_PATTERN_TYPE = 'PATN', + B_POINTER_TYPE = 'PNTR', + B_POINT_TYPE = 'BPNT', + B_RAW_TYPE = 'RAWT', + B_RECT_TYPE = 'RECT', + B_REF_TYPE = 'RREF', + B_RGB_32_BIT_TYPE = 'RGBB', + B_RGB_COLOR_TYPE = 'RGBC', + B_SIZE_T_TYPE = 'SIZT', + B_SSIZE_T_TYPE = 'SSZT', + B_STRING_TYPE = 'CSTR', + B_TIME_TYPE = 'TIME', + B_UINT64_TYPE = 'ULLG', + B_UINT32_TYPE = 'ULNG', + B_UINT16_TYPE = 'USHT', + B_UINT8_TYPE = 'UBYT', + B_MEDIA_PARAMETER_TYPE = 'BMCT', + B_MEDIA_PARAMETER_WEB_TYPE = 'BMCW', + B_MEDIA_PARAMETER_GROUP_TYPE= 'BMCG', + + /* deprecated, do not use */ + B_ASCII_TYPE = 'TEXT' /* use B_STRING_TYPE instead */ +}; + + +typedef struct fs_info +{ + beos_dev_t dev; + beos_ino_t root; + uint32 flags; +// beos_off_t block_size; + uint32 block_size; + beos_off_t io_size; +// beos_off_t total_blocks; +// beos_off_t free_blocks; + uint32 total_blocks; + uint32 free_blocks; + beos_off_t total_nodes; + beos_off_t free_nodes; + char device_name[128]; + char volume_name[B_FILE_NAME_LENGTH]; + char fsh_name[B_OS_NAME_LENGTH]; +} fs_info; + +typedef struct beos_stat +{ + uint32 st_dev; + uint32 st_nlink; + uint32 st_uid; + uint32 st_gid; + uint32 st_size; + uint32 st_blksize; + uint32 st_rdev; + uint32 st_ino; + uint32 st_mode; + uint32 st_atime; + uint32 st_mtime; + uint32 st_ctime; +} beos_stat; + + +bool IsValidUser(char *user, char *domain, char *password); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/betalk.h new file mode 100644 index 0000000000..f00ef2e1b0 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +#include //linux +#include +#include +#include +#include +#include +#include +#include +#include // windows +#include +#include // windows +#include +#include // windows +#include // windows +#include // windows + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRINTER_INKJET 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 8192 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 64 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'' || (c)=='\\') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct userRights +{ + char *user; + int rights; + bool isGroup; + struct userRights *next; +} bt_user_rights; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +#define BT_COOKIE_SIZE 4 +#define BT_COOKIE_BUFFER_SIZE 4096 +#define BT_QUERY_COOKIE_SIZE 4 +#define BT_FILE_HANDLE_SIZE 32 + +typedef struct btFileHandle +{ + char opaque[BT_FILE_HANDLE_SIZE]; +} btFileHandle; + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket packet; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetHandle(bt_inPacket *packet, btFileHandle *fhandle); +void btRPCGetStat(bt_inPacket *packet, beos_stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutHandle(bt_outPacket *packet, btFileHandle *fhandle); +void btRPCPutStat(bt_outPacket *packet, beos_stat *st); + +bt_rpccall * btRPCInvoke(int session, bt_outPacket *packet); +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error, int length); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ctrlpan.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ctrlpan.cpp new file mode 100644 index 0000000000..28dabd7560 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ctrlpan.cpp @@ -0,0 +1,90 @@ +// CtrlPan.cpp +// Source for CControlPanel + +#include "stdafx.h" +#include "CtrlPan.h" + +// static data +CControlPanel *CControlPanel::m_pThis = NULL; + +CControlPanel::CControlPanel() +{ + // Set up the static object pointer + m_pThis = this; +} + +CControlPanel::~CControlPanel() +{ +} + +////////////////////////////////////////////////////////////////////////////// +// Callback function (exported) + +// static member functions (callbacks) +LONG APIENTRY CControlPanel::CPlApplet(HWND hwndCPl,UINT uMsg,LONG lParam1,LONG lParam2) +{ + // Get a pointer to the C++ object + CControlPanel *pCtrl = m_pThis; + ASSERT(pCtrl); + switch (uMsg) + { + case CPL_DBLCLK: return(pCtrl->OnDblclk(hwndCPl,lParam1,lParam2)); + case CPL_EXIT: return(pCtrl->OnExit()); + case CPL_GETCOUNT: return(pCtrl->OnGetCount()); + case CPL_INIT: return(pCtrl->OnInit()); + case CPL_NEWINQUIRE: return(pCtrl->OnInquire(lParam1,(NEWCPLINFO *) lParam2)); + case CPL_INQUIRE: return(0); // not handled + case CPL_SELECT: return(pCtrl->OnSelect(lParam1,lParam2)); + case CPL_STOP: return(pCtrl->OnStop(lParam1,lParam2)); + default: break; + } + return(1); // not processed +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Default command handlers + +LONG CControlPanel::OnDblclk(HWND hwndCPl,UINT uAppNum,LONG lData) +{ + // Show the dialog + return(0); // OK +} + +LONG CControlPanel::OnExit() +{ + return(0); // OK +} + +LONG CControlPanel::OnGetCount() +{ + return(1); // default is support for one dialog box +} + +LONG CControlPanel::OnInit() +{ + return(1); // OK +} + +LONG CControlPanel::OnInquire(UINT uAppNum,NEWCPLINFO *pInfo) +{ + // Fill in the data + pInfo->dwSize = sizeof(NEWCPLINFO); // important + pInfo->dwFlags = 0; + pInfo->dwHelpContext = 0; + pInfo->lData = 0; + pInfo->hIcon = ::LoadIcon(AfxGetResourceHandle(),MAKEINTRESOURCE(1)); + strcpy(pInfo->szName,"Applet"); + strcpy(pInfo->szInfo,"Bar Code Scanner Applet"); + strcpy(pInfo->szHelpFile,""); + return(0); // OK (don't send CPL_INQUIRE msg) +} + +LONG CControlPanel::OnSelect(UINT uAppNum,LONG lData) +{ + return(1); // not handled +} + +LONG CControlPanel::OnStop(UINT uAppNum,LONG lData) +{ + return(1); // not handled +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ctrlpan.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ctrlpan.h new file mode 100644 index 0000000000..80e7f9892c --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/ctrlpan.h @@ -0,0 +1,30 @@ +// CtrlPan.h + +#ifndef _CTRLPAN_H_ +#define _CTRLPAN_H_ + +#include // control panel definitions + +class CControlPanel +{ +public: + CControlPanel(); + virtual ~CControlPanel(); + + // Event handlers + virtual LONG OnDblclk(HWND hwndCPl,UINT uAppNum,LONG lData); + virtual LONG OnExit(); + virtual LONG OnGetCount(); + virtual LONG OnInit(); + virtual LONG OnInquire(UINT uAppNum,NEWCPLINFO *pInfo); + virtual LONG OnSelect(UINT uAppNum,LONG lData); + virtual LONG OnStop(UINT uAppNum,LONG lData); + + // static member functions (callbacks) + static LONG APIENTRY CPlApplet(HWND hwndCPl,UINT uMsg,LONG lParam1,LONG lParam2); + + // static data + static CControlPanel *m_pThis; // nasty hack to get object ptr +}; + +#endif // _CTRLPAN_H_ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/folderview.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/folderview.cpp new file mode 100644 index 0000000000..e3640398d6 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/folderview.cpp @@ -0,0 +1,19 @@ +// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++ + +// NOTE: Do not modify the contents of this file. If this class is regenerated by +// Microsoft Visual C++, your modifications will be overwritten. + + +#include "stdafx.h" +#include "folderview.h" + +///////////////////////////////////////////////////////////////////////////// +// CFolderview + +IMPLEMENT_DYNCREATE(CFolderview, CWnd) + +///////////////////////////////////////////////////////////////////////////// +// CFolderview properties + +///////////////////////////////////////////////////////////////////////////// +// CFolderview operations diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/folderview.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/folderview.h new file mode 100644 index 0000000000..0d09c6de82 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/folderview.h @@ -0,0 +1,465 @@ +#pragma once + +// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++ + +// NOTE: Do not modify the contents of this file. If this class is regenerated by +// Microsoft Visual C++, your modifications will be overwritten. + +///////////////////////////////////////////////////////////////////////////// +// CFolderview wrapper class + +class CFolderview : public CWnd +{ +protected: + DECLARE_DYNCREATE(CFolderview) +public: + CLSID const& GetClsid() + { + static CLSID const clsid + = { 0xFBF52F2D, 0x9B93, 0x11D2, { 0xB4, 0x82, 0x0, 0x20, 0xAF, 0xD6, 0x9D, 0xE6 } }; + return clsid; + } + virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, + const RECT& rect, CWnd* pParentWnd, UINT nID, + CCreateContext* pContext = NULL) + { + return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID); + } + + BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, + UINT nID, CFile* pPersist = NULL, BOOL bStorage = FALSE, + BSTR bstrLicKey = NULL) + { + return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID, + pPersist, bStorage, bstrLicKey); + } + +// Attributes +public: +enum +{ + Flat = 0, + ThreeD = 1 +}AppearanceConstants; +enum +{ + None = 0, + FixedSingle = 1 +}BorderStyleConstants; +enum +{ + AllAttributes = -1, + CapabilityAttributes = 375, + DisplayAttributes = 983040, + ContentsAttributes = -2147483648, + MiscellaneousAttributes = -1048576 +}AttributesMask; +enum +{ + CanCopy = 1, + CanMove = 2, + CanLink = 4, + CanRename = 16, + CanDelete = 32, + HasPropSheet = 64, + DropTarget = 256, + Shortcut = 65536, + Share = 131072, + ReadOnly = 262144, + Hidden = 524288, + HasSubfolder = -2147483648, + IsFileSysAncestor = 268435456, + IsFolder = 536870912, + IsFileSystem = 1073741824, + Validate = 16777216, + Removable = 33554432, + IsCompressed = 67108864, + IsBrowsable = 134217728, + NonEnumerated = 1048576, + NewContent = 2097152 +}AttributesEnum; +enum +{ + Desktop = 0, + Internet = 1, + Programs = 2, + ControlPanel = 3, + Printers = 4, + Personal = 5, + Favorites = 6, + Startup = 7, + Recent = 8, + SendTo = 9, + Recycled = 10, + StartMenu = 11, + DesktopDir = 16, + MyComputer = 17, + Network = 18, + NetHood = 19, + Fonts = 20, + Templates = 21, + CommonStartMenu = 22, + CommonPrograms = 23, + CommonStartup = 24, + CommonDesktopDir = 25, + AppData = 26, + PrintHood = 27, + AltStartup = 29, + CommonAltStartup = 30, + CommonFavorites = 31, + InternetCache = 32, + Cookies = 33, + History = 34 +}SpecialFolderPathConstants; + + +// Operations +public: + +// IFolderView + +// Functions +// + +void put_BackColor(unsigned long newValue) +{ + static BYTE parms[] = VTS_UI4 ; + InvokeHelper(DISPID_BACKCOLOR, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +unsigned long get_BackColor() +{ + unsigned long result; + InvokeHelper(DISPID_BACKCOLOR, DISPATCH_PROPERTYGET, VT_UI4, (void*)&result, NULL); + return result; +} +void put_ForeColor(unsigned long newValue) +{ + static BYTE parms[] = VTS_UI4 ; + InvokeHelper(DISPID_FORECOLOR, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +unsigned long get_ForeColor() +{ + unsigned long result; + InvokeHelper(DISPID_FORECOLOR, DISPATCH_PROPERTYGET, VT_UI4, (void*)&result, NULL); + return result; +} +long get_Appearance() +{ + long result; + InvokeHelper(DISPID_APPEARANCE, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); + return result; +} +void put_Appearance(long newValue) +{ + static BYTE parms[] = VTS_I4 ; + InvokeHelper(DISPID_APPEARANCE, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +long get_BorderStyle() +{ + long result; + InvokeHelper(DISPID_BORDERSTYLE, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); + return result; +} +void put_BorderStyle(long newValue) +{ + static BYTE parms[] = VTS_I4 ; + InvokeHelper(DISPID_BORDERSTYLE, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +BOOL get_HasLines() +{ + BOOL result; + InvokeHelper(0x1, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_HasLines(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0x1, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +BOOL get_HasButtons() +{ + BOOL result; + InvokeHelper(0x2, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_HasButtons(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0x2, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +BOOL get_HasLinesAtRoot() +{ + BOOL result; + InvokeHelper(0x3, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_HasLinesAtRoot(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0x3, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +BOOL get_ShowSelAlways() +{ + BOOL result; + InvokeHelper(0x4, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_ShowSelAlways(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0x4, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +VARIANT get_Folders() +{ + VARIANT result; + InvokeHelper(0x6, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&result, NULL); + return result; +} +BOOL get_HasCheckBoxes() +{ + BOOL result; + InvokeHelper(0x5, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_HasCheckBoxes(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0x5, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +BOOL get_DisplayShareName() +{ + BOOL result; + InvokeHelper(0x7, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_DisplayShareName(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0x7, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +LPDISPATCH get_FoldersCheck() +{ + LPDISPATCH result; + InvokeHelper(0x8, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, NULL); + return result; +} +BOOL get_OverlayIcons() +{ + BOOL result; + InvokeHelper(0x9, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_OverlayIcons(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0x9, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +CString get_SpecialFolderPath(long specialFolder) +{ + CString result; + static BYTE parms[] = VTS_I4 ; + InvokeHelper(0xa, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, parms, specialFolder); + return result; +} +VARIANT get_SelectedFolder() +{ + VARIANT result; + InvokeHelper(0xb, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&result, NULL); + return result; +} +void put_SelectedFolder(VARIANT newValue) +{ + static BYTE parms[] = VTS_VARIANT ; + InvokeHelper(0xb, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, &newValue); +} +BOOL get_EnableShellMenu() +{ + BOOL result; + InvokeHelper(0xc, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_EnableShellMenu(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0xc, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +BOOL get_AutoUpdate() +{ + BOOL result; + InvokeHelper(0xf, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_AutoUpdate(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0xf, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +long get_VisibleCount() +{ + long result; + InvokeHelper(0x10, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); + return result; +} +LPDISPATCH get_HitTest(long X, long Y) +{ + LPDISPATCH result; + static BYTE parms[] = VTS_I4 VTS_I4 ; + InvokeHelper(0x11, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, parms, X, Y); + return result; +} +BOOL get_HiddenFolders() +{ + BOOL result; + InvokeHelper(0x12, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_HiddenFolders(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0x12, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +LPDISPATCH get_FirstVisibleFolder() +{ + LPDISPATCH result; + InvokeHelper(0x13, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, NULL); + return result; +} +void put_FirstVisibleFolder(LPDISPATCH newValue) +{ + static BYTE parms[] = VTS_DISPATCH ; + InvokeHelper(0x13, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +void Refresh() +{ + InvokeHelper(0xd, DISPATCH_METHOD, VT_EMPTY, NULL, NULL); +} +void EnsureVisible(VARIANT newVal) +{ + static BYTE parms[] = VTS_VARIANT ; + InvokeHelper(0xe, DISPATCH_METHOD, VT_EMPTY, NULL, parms, &newVal); +} +BOOL get_Enabled() +{ + BOOL result; + InvokeHelper(DISPID_ENABLED, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_Enabled(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(DISPID_ENABLED, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +LPDISPATCH get_Folder(VARIANT anPath) +{ + LPDISPATCH result; + static BYTE parms[] = VTS_VARIANT ; + InvokeHelper(0x14, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, parms, &anPath); + return result; +} +BOOL get_IconsVisible() +{ + BOOL result; + InvokeHelper(0x15, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_IconsVisible(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0x15, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +LPDISPATCH get_Header() +{ + LPDISPATCH result; + InvokeHelper(0x16, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, NULL); + return result; +} +CString get_Version() +{ + CString result; + InvokeHelper(0x17, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL); + return result; +} +void put_Version(LPCTSTR newValue) +{ + static BYTE parms[] = VTS_BSTR ; + InvokeHelper(0x17, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +CString get_ExploreFromHere() +{ + CString result; + InvokeHelper(0x18, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL); + return result; +} +void put_ExploreFromHere(LPCTSTR newValue) +{ + static BYTE parms[] = VTS_BSTR ; + InvokeHelper(0x18, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +void About() +{ + InvokeHelper(0x19, DISPATCH_METHOD, VT_EMPTY, NULL, NULL); +} +CString get_LicenseKey() +{ + CString result; + InvokeHelper(0x1a, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL); + return result; +} +void put_LicenseKey(LPCTSTR newValue) +{ + static BYTE parms[] = VTS_BSTR ; + InvokeHelper(0x1a, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +long get_DropFilesCount() +{ + long result; + InvokeHelper(0x1b, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); + return result; +} +CString get_DropFilesPathName(long nIndex) +{ + CString result; + static BYTE parms[] = VTS_I4 ; + InvokeHelper(0x1c, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, parms, nIndex); + return result; +} +BOOL get_AllowDropFiles() +{ + BOOL result; + InvokeHelper(0x1d, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} +void put_AllowDropFiles(BOOL newValue) +{ + static BYTE parms[] = VTS_BOOL ; + InvokeHelper(0x1d, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +long get_hwnd() +{ + long result; + InvokeHelper(DISPID_HWND, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); + return result; +} +void put_Font(LPDISPATCH newValue) +{ + static BYTE parms[] = VTS_DISPATCH ; + InvokeHelper(DISPID_FONT, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); +} +LPDISPATCH get_Font() +{ + LPDISPATCH result; + InvokeHelper(DISPID_FONT, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, NULL); + return result; +} +void putref_Font(LPDISPATCH newValue) +{ + static BYTE parms[] = VTS_DISPATCH ; + InvokeHelper(DISPID_FONT, DISPATCH_PROPERTYPUTREF, VT_EMPTY, NULL, parms, newValue); +} + +// Properties +// + + + +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/mtvfolder.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/mtvfolder.cpp new file mode 100644 index 0000000000..c75ed18839 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/mtvfolder.cpp @@ -0,0 +1,99 @@ +// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++ + +// NOTE: Do not modify the contents of this file. If this class is regenerated by +// Microsoft Visual C++, your modifications will be overwritten. + + +#include "stdafx.h" +#include "mtvfolder.h" + + +///////////////////////////////////////////////////////////////////////////// +// CMTVFolder properties + +///////////////////////////////////////////////////////////////////////////// +// CMTVFolder operations + +long CMTVFolder::GetHandle() +{ + long result; + InvokeHelper(0x4, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); + return result; +} + +CString CMTVFolder::GetDisplayName() +{ + CString result; + InvokeHelper(0x5, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL); + return result; +} + +CString CMTVFolder::GetPathName() +{ + CString result; + InvokeHelper(0x6, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL); + return result; +} + +VARIANT CMTVFolder::GetFolders() +{ + VARIANT result; + InvokeHelper(0x7, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&result, NULL); + return result; +} + +CString CMTVFolder::GetShareName() +{ + CString result; + InvokeHelper(0x8, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL); + return result; +} + +CString CMTVFolder::GetName() +{ + CString result; + InvokeHelper(0x9, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL); + return result; +} + +BOOL CMTVFolder::GetCheck() +{ + BOOL result; + InvokeHelper(0xa, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); + return result; +} + +void CMTVFolder::SetCheck(BOOL bNewValue) +{ + static BYTE parms[] = + VTS_BOOL; + InvokeHelper(0xa, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, + bNewValue); +} + +LPUNKNOWN CMTVFolder::GetShellFolder() +{ + LPUNKNOWN result; + InvokeHelper(0xb, DISPATCH_PROPERTYGET, VT_UNKNOWN, (void*)&result, NULL); + return result; +} + +long CMTVFolder::GetAttributes(long dwMask) +{ + long result; + static BYTE parms[] = + VTS_I4; + InvokeHelper(0xc, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, parms, + dwMask); + return result; +} + +BOOL CMTVFolder::GetAttribute(long anAttribute) +{ + BOOL result; + static BYTE parms[] = + VTS_I4; + InvokeHelper(0xd, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, parms, + anAttribute); + return result; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/mtvfolder.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/mtvfolder.h new file mode 100644 index 0000000000..f2e1e9c839 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/mtvfolder.h @@ -0,0 +1,43 @@ +#if !defined(AFX_MTVFOLDER_H__60DF2AD0_F62B_11D5_90FA_00C04F0972A7__INCLUDED_) +#define AFX_MTVFOLDER_H__60DF2AD0_F62B_11D5_90FA_00C04F0972A7__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++ + +// NOTE: Do not modify the contents of this file. If this class is regenerated by +// Microsoft Visual C++, your modifications will be overwritten. + +///////////////////////////////////////////////////////////////////////////// +// CMTVFolder wrapper class + +class CMTVFolder : public COleDispatchDriver +{ +public: + CMTVFolder() {} // Calls COleDispatchDriver default constructor + CMTVFolder(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {} + CMTVFolder(const CMTVFolder& dispatchSrc) : COleDispatchDriver(dispatchSrc) {} + +// Attributes +public: + +// Operations +public: + long GetHandle(); + CString GetDisplayName(); + CString GetPathName(); + VARIANT GetFolders(); + CString GetShareName(); + CString GetName(); + BOOL GetCheck(); + void SetCheck(BOOL bNewValue); + LPUNKNOWN GetShellFolder(); + long GetAttributes(long dwMask); + BOOL GetAttribute(long anAttribute); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MTVFOLDER_H__60DF2AD0_F62B_11D5_90FA_00C04F0972A7__INCLUDED_) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/printing.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/printing.h new file mode 100644 index 0000000000..21976dadab --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/printing.h @@ -0,0 +1,49 @@ +#ifndef __printing_h__ +#define __printing_h__ + +#include "beCompat.h" +#include "betalk.h" + + +typedef struct +{ + char printerName[MAX_NAME_LENGTH]; + char deviceName[B_FILE_NAME_LENGTH]; + char deviceType[MAX_NAME_LENGTH]; + char spoolDir[B_PATH_NAME_LENGTH]; + + bool killed; + bool used; + + bt_user_rights *rights; + int security; + + HANDLE handlerID; +} bt_printer; + + +typedef struct printJob +{ + char jobName[MAX_DESC_LENGTH + 1]; + char jobFile[B_PATH_NAME_LENGTH + 1]; + uint32 sourceAddr; + char sourceUser[MAX_USERNAME_LENGTH + 1]; + char status[MAX_DESC_LENGTH + 1]; + struct printJob *next; +} bt_print_job; + + +// Although there is no maximum number of entries that can be queued for +// printing, except as limited by available disk space, for simplicity +// BeServed will only report on the first MAX_PRINT_JOBS in the queue. +// This keeps the print job query from requiring repeated calls to handle +// large volume. + +#define MAX_PRINT_JOBS (BT_MAX_IO_BUFFER / sizeof(bt_print_job)) + +int btPrintJobNew(char *printerName, char *user, char *password, int client_s_addr, char *jobName, char *jobId); +int btPrintJobData(char *printerName, char *jobId, char *jobData, int dataLen); +int btPrintJobCommit(char *printerName, char *jobId); +int btPrintJobQuery(char *printerName, bt_print_job *jobList); + +#endif \ No newline at end of file diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/FileSharing.ico b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/FileSharing.ico new file mode 100644 index 0000000000..696eef733f Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/FileSharing.ico differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/bitmap1.bmp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/bitmap1.bmp new file mode 100644 index 0000000000..1f07309b90 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/bitmap1.bmp differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/filesharing.bmp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/filesharing.bmp new file mode 100644 index 0000000000..20a30afa6c Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/filesharing.bmp differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/group.bmp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/group.bmp new file mode 100644 index 0000000000..1973e305f5 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/group.bmp differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/icon1.ico b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/icon1.ico new file mode 100644 index 0000000000..139772c418 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/icon1.ico differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/idi_globe.ico b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/idi_globe.ico new file mode 100644 index 0000000000..569ab145d5 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/idi_globe.ico differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/lightbulb.ico b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/lightbulb.ico new file mode 100644 index 0000000000..a0046dc73b Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/lightbulb.ico differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/options.ico b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/options.ico new file mode 100644 index 0000000000..828135fe2a Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/options.ico differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/padlock.ico b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/padlock.ico new file mode 100644 index 0000000000..d82b5d984a Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/padlock.ico differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/printer.ico b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/printer.ico new file mode 100644 index 0000000000..58e3c25c45 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/printer.ico differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/scanappl.ico b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/scanappl.ico new file mode 100644 index 0000000000..eb1b8f5d27 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/scanappl.ico differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/scanappl.rc2 b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/scanappl.rc2 new file mode 100644 index 0000000000..3f36904f57 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/scanappl.rc2 @@ -0,0 +1,13 @@ +// +// SCANAPPL.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/sharing.ico b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/sharing.ico new file mode 100644 index 0000000000..1a99cdbe84 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/sharing.ico differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/user.bmp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/user.bmp new file mode 100644 index 0000000000..c02d6ad826 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/user.bmp differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/volume.bmp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/volume.bmp new file mode 100644 index 0000000000..244ebfd3e1 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/res/volume.bmp differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/resource.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/resource.h new file mode 100644 index 0000000000..8ec1ed98ae --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/resource.h @@ -0,0 +1,84 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by FileSharing.rc +// +#define IDD_PRINTERSHARING_DIALOG 102 +#define IDR_MAINFRAME 129 +#define IDD_PRINTER_PROPERTIES 129 +#define IDB_FILESHARING 130 +#define IDD_MAINPANEL 130 +#define IDB_VOLUME 131 +#define IDI_PRINTER 131 +#define IDD_SHARE_PROPERTIES 132 +#define IDD_BROWSER 134 +#define IDI_VOLUME 137 +#define IDI_SHARING 138 +#define IDI_OPTIONS 139 +#define IDI_GLOBE 140 +#define IDB_USER 141 +#define IDB_GROUP 142 +#define IDD_SECURITY 142 +#define IDD_FILESHARING_DIALOG 143 +#define IDI_PADLOCK 144 +#define IDI_LIGHTBULB 145 +#define IDD_DOMAIN_USERS 146 +#define IDD_MANAGE_QUEUE 147 +#define IDC_ACTIVITY_LOG 1000 +#define IDC_PRINTERS 1000 +#define IDC_LOG_FILE_NAME 1001 +#define IDC_NEW_PRINTER 1001 +#define IDC_SHARE_LIST 1002 +#define IDC_EDIT_PRINTER 1002 +#define IDC_PRINTER_MODEL 1002 +#define IDC_CURRENT 1003 +#define IDC_MAIN_HEADING 1003 +#define IDC_MSG 1004 +#define IDC_SHARE_NEW 1004 +#define IDC_REMOVE_PRINTER 1004 +#define IDC_SHARE_EDIT 1005 +#define IDC_MAX_CLIENTS_SPIN 1006 +#define IDC_SHARE_REMOVE 1006 +#define IDC_PRINTER_DEVICE 1006 +#define IDC_MAX_CLIENTS 1007 +#define IDC_SHARE_HEADING 1007 +#define IDC_PRINTER_HEADING 1007 +#define IDC_SHARE_NAME 1008 +#define IDC_PRINTER_NAME 1008 +#define IDC_SHARE_PATH 1009 +#define IDC_PRINTER_REMOVE 1009 +#define IDC_SHARE_BROWSE 1010 +#define IDC_QUEUE_PATH 1010 +#define IDC_UPDATE_LOG 1011 +#define IDC_SHARE_WRITE 1011 +#define IDC_PRINTER_BROWSE 1011 +#define IDC_SHARE_LINKS 1012 +#define IDC_PRINTER_TYPE 1012 +#define IDC_SHARE_ADD 1013 +#define IDC_FOLDERVIEW 1013 +#define IDC_PRINTER_ADD 1013 +#define IDC_OPTIONS_HEADING 1014 +#define IDC_MANAGE 1014 +#define IDC_DOMAIN_HEADING 1015 +#define IDC_QUEUE_LIST 1015 +#define IDC_DOMAIN_USERS 1016 +#define IDC_REMOVE_JOB 1016 +#define IDC_SECURITY_TYPE 1017 +#define IDC_PAUSE_JOB 1017 +#define IDC_SECURITY_SERVER 1018 +#define IDC_DOMAIN_RIGHTS 1020 +#define IDC_SECURITY 1021 +#define IDC_PORT_NUMBER 1022 +#define IDC_SHAREDTHREADS 1028 +#define IDC_SOCKET_TIMEOUT 1029 +#define IDC_SOCKET_TIMEOUT_SPIN 1030 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 131 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/rpc.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/rpc.cpp new file mode 100644 index 0000000000..ad44ebeed2 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/rpc.cpp @@ -0,0 +1,474 @@ +#include "stdafx.h" + +#include "becompat.h" +#include "betalk.h" +#include "rpc.h" + +#include "signal.h" + + +int btRPCConnect(unsigned int serverIP, int port) +{ + struct sockaddr_in serverAddr; + int session; + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(port); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(serverIP); + + // Create a new socket to receive incoming requests. + session = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (session == INVALID_SOCKET) + return INVALID_SOCKET; + + // Bind that socket to the address constructed above. + if (connect(session, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return INVALID_SOCKET; + + return session; +} + +bool btRPCSend(int session, bt_outPacket *outPacket) +{ + unsigned int bytesSent; + + // The XID will be 0. + btRPCPutInt32(outPacket, 0); + btRPCPutChar(outPacket, BT_CMD_TERMINATOR); + + bytesSent = 0; + do + { + int bytes = btSend(session, outPacket->buffer + bytesSent, outPacket->length - bytesSent, 0); + if (bytes == -1) + return false; + + bytesSent += bytes; + } while (bytesSent < outPacket->length); + + return true; +} + +bool btRPCCheckSignature(int session) +{ + char signature[20]; + unsigned int sigLen; + + sigLen = strlen(BT_RPC_SIGNATURE); + memset(signature, 0, sigLen); + if (btRecv(session, signature, sigLen, 0) == -1) + return false; + + // Check the signature's validity. + signature[sigLen] = 0; + return (strcmp(signature, BT_RPC_SIGNATURE) == 0); +} + +// btRPCSimpleCall() +// +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket) +{ + struct timeval timeout; + bt_inPacket *inPacket; + fd_set sockSet; + char *buffer; + int session; + int32 bytesRead, xid, length; + + // Establish a connection with the requested server, on the requested port. + // If we can't connect, abort and return a NULL packet. + inPacket = NULL; + session = btRPCConnect(serverIP, port); + if (session == INVALID_SOCKET) + return NULL; + + // If we connected, send the requested RPC packet. If the packet cannot be + // sent, the connection has dropped and we'll abort the call. + if (!btRPCSend(session, outPacket)) + { + closesocket(session); + return NULL; + } + + // Set a reasonable timeout period. Select() is used in leiu of alarm() because + // select() also aborts on error, alarm() effects all threads in a process. + FD_ZERO(&sockSet); + timeout.tv_sec = 8; + timeout.tv_usec = 0; + + // Block in select() waiting for activity. This will block until data is available + // or until a socket error is pending. + FD_SET(session, &sockSet); + select(session + 1, &sockSet, NULL, NULL, &timeout); + + // If our socket has data pending, then read the incoming RPC response packet. + // This should consist of a valid RPC signature, a tranaction ID (xid), the length + // of the variable data, and the data itself. + if (FD_ISSET(session, &sockSet)) + if (btRPCCheckSignature(session)) + { + if (btRecv(session, &xid, sizeof(int32), 0) == -1 || + btRecv(session, &length, sizeof(int32), 0) == -1) + goto abortCall; + + // Now allocate a buffer of the appropriate length. If one cannot be + // allocated, we won't be able to store incoming information and the call + // must be aborted. + if (length > 0 && length < BT_RPC_MAX_PACKET_SIZE) + { + buffer = (char *) malloc(length + 1); + if (buffer) + { + // Read the remaining packet contents. The btRecv() function takes + // care of restarting the recv() when signal interrupts occur. It + // will always return -1 on error, even upon orderly shutdown of the peer. + bytesRead = 0; + do + { + int bytes = btRecv(session, buffer + bytesRead, length - bytesRead, 0); + if (bytes == -1) + { + free(buffer); + goto abortCall; + } + + bytesRead += bytes; + } while (bytesRead < length); + + // Terminate the buffer. + buffer[length] = 0; + + // Allocate a new incoming packet and set its buffer and length. + inPacket = (bt_inPacket *) malloc(sizeof(bt_inPacket)); + if (inPacket) + { + inPacket->buffer = buffer; + inPacket->length = length; + inPacket->offset = 0; + } + else + free(buffer); + } + } + } + + // Execution can naturally lead here or we can jump here from a failed attempt to + // send or receive an RPC packet. The socket is closed and the current incoming + // packet returned, which will be NULL upon failure. +abortCall: + shutdown(session, 2); + close(session); + return inPacket; +} + +// btRecv() +// +int btRecv(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = recv(sock, (char *) data, dataLen, flags); + if (bytes == 0) + return -1; + else if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +// btSend() +// +int btSend(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = send(sock, (const char *) data, dataLen, flags); + if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +void btDestroyInPacket(bt_inPacket *packet) +{ + if (packet) + { + if (packet->buffer) + free(packet->buffer); + + free(packet); + } +} + +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length) +{ + bt_outPacket *packet; + + packet = (bt_outPacket *) malloc(sizeof(bt_outPacket)); + if (!packet) + return NULL; + + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + { + free(packet); + return NULL; + } + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + +// btRPCPutChar(packet, BT_RPC_VERSION_HI); +// btRPCPutChar(packet, BT_RPC_VERSION_LO); + btRPCPutInt32(packet, 7 + (8 * argc) + length); + btRPCPutChar(packet, command); + btRPCPutChar(packet, argc); + + return packet; +} + +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length) +{ + btRPCPutInt32(packet, type); + btRPCPutInt32(packet, length); + btRPCPutBinary(packet, data, length); +} + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error, int length) +{ + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + return; + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + btRPCPutInt32(packet, xid); + btRPCPutInt32(packet, 0); + btRPCPutInt32(packet, error); +} + +void btRPCSendAck(int client, bt_outPacket *packet) +{ + int32 bytesSent; + + if (packet) + if (packet->buffer) + { + *(int32 *)(&packet->buffer[9]) = packet->length - 13; + + bytesSent = 0; + do + { + bytesSent += send(client, packet->buffer + bytesSent, packet->length - bytesSent, 0); + } while (bytesSent < packet->length); + + free(packet->buffer); + } +} + +unsigned char btRPCGetChar(bt_inPacket *packet) +{ + unsigned char value; + + if (packet->offset < packet->length) + value = (unsigned char) packet->buffer[packet->offset]; + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + if (bytes > 0) + memcpy(str, &packet->buffer[packet->offset], bytes); + + str[bytes] = 0; + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return ERANGE; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return ERANGE; + + if (length < bytes) + return ERANGE; + + if (bytes > 0) + memcpy(buffer, &packet->buffer[packet->offset], bytes); + + packet->offset += bytes; + return bytes; +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, B_HOST_TO_LENDIAN_INT32(length)); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutHandle(bt_outPacket *packet, btFileHandle *fhandle) +{ + if (packet && fhandle) + { + btRPCGrowPacket(packet, BT_FILE_HANDLE_SIZE); + memcpy(&packet->buffer[packet->length], fhandle->opaque, BT_FILE_HANDLE_SIZE); + packet->length += BT_FILE_HANDLE_SIZE; + } +} + +void btRPCGetStat(bt_inPacket *packet, beos_stat *st) +{ + st->st_dev = 0; + st->st_nlink = btRPCGetInt32(packet); + st->st_uid = btRPCGetInt32(packet); + st->st_gid = btRPCGetInt32(packet); + st->st_size = (int32) btRPCGetInt64(packet); + st->st_blksize = btRPCGetInt32(packet); + st->st_rdev = btRPCGetInt32(packet); + st->st_ino = (int32) btRPCGetInt64(packet); + st->st_mode = btRPCGetInt32(packet); + st->st_atime = btRPCGetInt32(packet); + st->st_mtime = btRPCGetInt32(packet); + st->st_ctime = btRPCGetInt32(packet); +} + +void btRPCPutStat(bt_outPacket *packet, beos_stat *st) +{ + if (packet && st) + { + btRPCPutInt32(packet, (int) st->st_nlink); + btRPCPutInt32(packet, (int) st->st_uid); + btRPCPutInt32(packet, (int) st->st_gid); + btRPCPutInt64(packet, (int64) st->st_size); + btRPCPutInt32(packet, (int) 1024); + btRPCPutInt32(packet, (int) st->st_rdev); + btRPCPutInt64(packet, (int64) st->st_ino); + btRPCPutInt32(packet, (int) st->st_mode); + btRPCPutInt32(packet, (int) st->st_atime); + btRPCPutInt32(packet, (int) st->st_mtime); + btRPCPutInt32(packet, (int) st->st_ctime); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/rpc.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/rpc.h new file mode 100644 index 0000000000..3fb61d9b89 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/rpc.h @@ -0,0 +1,34 @@ +// rpc.h + +#ifndef _BETALK_H_ +#include "beCompat.h" +#include "betalk.h" +#endif + +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket); +int btRPCConnect(unsigned int serverIP, int port); +bool btRPCSend(int session, bt_outPacket *outPacket); +bool btRPCCheckSignature(int session); +void btDestroyInPacket(bt_inPacket *packet); +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error, int length); +void btRPCSendAck(int client, bt_outPacket *packet); +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char *btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +void btRPCGrowPacket(bt_outPacket *packet, int bytes); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutHandle(bt_outPacket *packet, btFileHandle *fhandle); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/scanappl.suo b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/scanappl.suo new file mode 100644 index 0000000000..82552ec615 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/scanappl.suo differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/scanpan.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/scanpan.cpp new file mode 100644 index 0000000000..10fd4c491a --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/scanpan.cpp @@ -0,0 +1,27 @@ +// ScanPan.cpp + +#include "stdafx.h" +#include "FileSharing.h" +#include "MainPanel.h" + +LONG CScanPanel::OnInquire(UINT uAppNum,NEWCPLINFO *pInfo) +{ + // Fill in the data + pInfo->dwSize = sizeof(NEWCPLINFO); // important + pInfo->dwFlags = 0; + pInfo->dwHelpContext = 0; + pInfo->lData = 0; + pInfo->hIcon = ::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME)); + strcpy(pInfo->szName, "BeServed File Sharing"); + strcpy(pInfo->szInfo, "BeServed"); + strcpy(pInfo->szHelpFile,""); + return 0; // OK (don't send CPL_INQUIRE msg) +} + +LONG CScanPanel::OnDblclk(HWND hwndCPl,UINT uAppNum,LONG lData) +{ + // Create the dialog box using the parent window handle + CMainPanel dlg(CWnd::FromHandle(hwndCPl)); + dlg.DoModal(); + return(0); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/scanpan.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/scanpan.h new file mode 100644 index 0000000000..f08f9c01e7 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing-Windows/scanpan.h @@ -0,0 +1,12 @@ +// ScanPan.h + +#include "ctrlpan.h" + +#define MYSERVICENAME "Bar Code Scanner Control" + +class CScanPanel : public CControlPanel +{ +public: + virtual LONG OnInquire(UINT uAppNum,NEWCPLINFO *pInfo); + virtual LONG OnDblclk(HWND hwndCPl,UINT uAppNum,LONG lData); +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/FileSharing.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/FileSharing.cpp new file mode 100644 index 0000000000..2ff80640b4 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/FileSharing.cpp @@ -0,0 +1,2075 @@ +// File Sharing Preferences Application +// +// FileSharing.cpp +// + +// TODO: +// 1. Make share properties panel modal but still work with file panel + +#include "Application.h" +#include "Window.h" +#include "Region.h" +#include "Alert.h" +#include "CheckBox.h" +#include "Button.h" +#include "TextControl.h" +#include "Menu.h" +#include "PopUpMenu.h" +#include "MenuItem.h" +#include "MenuField.h" +#include "FilePanel.h" +#include "FindDirectory.h" +#include "Path.h" +#include "Mime.h" +#include "Roster.h" +#include "Resources.h" + +#include "string.h" +#include "stdio.h" +#include "ctype.h" +#include "signal.h" +#include "unistd.h" + +#include "betalk.h" +#include "rpc.h" +//#include "besure_auth.h" + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#define BT_MAX_FILE_SHARES 128 + +#define MSG_SHARE_INVOKE 'SInv' +#define MSG_PATH_BROWSE 'PBrw' +#define MSG_SHARE_OK 'SOky' +#define MSG_SHARE_CANCEL 'SCan' +#define MSG_SHARE_REFRESH 'SRef' +#define MSG_NEW_SHARE 'SNew' +#define MSG_EDIT_SHARE 'SEdt' +#define MSG_REMOVE_SHARE 'SRem' +#define MSG_SHARE_DEPLOY 'SDep' +#define MSG_SHARE_SELECT 'SSel' +#define MSG_SHARE_PERMS 'SPrm' +#define MSG_EDIT_SECURITY 'ESec' + +#define MSG_PICKUSER_SELECT 'MSel' +#define MSG_PICKUSER_ADD 'PAdd' +#define MSG_PICKUSER_REMOVE 'PRem' + +#define MSG_DOMUSER_OK 'DOky' +#define MSG_DOMUSER_CANCEL 'DCan' +#define MSG_DOMUSER_SELECT 'DSel' + +#define ICON_USER_LARGE 111 +#define ICON_USER_SMALL 112 +#define ICON_GROUP_LARGE 115 +#define ICON_GROUP_SMALL 116 +#define ICON_DOMAIN_LARGE 109 +#define ICON_DOMAIN_SMALL 110 +#define ICON_SWITCH_LARGE 119 +#define ICON_SWITCH_SMALL 120 +#define ICON_LIGHT_LARGE 121 +#define ICON_PADLOCK_LARGE 122 +#define ICON_KEY_LARGE 123 + +#define WARN_REMOVE_SHARE "Removing this file share will prevent other users on your network from accessing certain files on this computer. Are you sure you want to remove this file share?" + +#ifndef iswhite +#define iswhite(c) ((c == ' ' || c == '\t')) +#endif + +typedef void op_refresh(int share); + +typedef struct userRights +{ + char *user; + int rights; + bool isGroup; + struct userRights *next; +} bt_user_rights; + +typedef struct fileShare +{ + char path[B_PATH_NAME_LENGTH]; + char name[B_FILE_NAME_LENGTH]; + + bool used; + bool readOnly; + bool followLinks; + + // What rights does each user have? + bt_user_rights *rights; + int security; + + int index; + struct fileShare *next; +} bt_fileShare_t; + +void printString(FILE *fp, const char *str); + +bt_fileShare_t fileShares[BT_MAX_FILE_SHARES]; +char tokBuffer[B_PATH_NAME_LENGTH], *tokPtr; +char authServerName[B_FILE_NAME_LENGTH], authKey[MAX_KEY_LENGTH + 1]; +unsigned int authServerIP = 0; + +char *keywords[] = +{ + "share", + "as", + "set", + "read", + "write", + "read-write", + "promiscuous", + "on", + "to", + "authenticate", + "with", + "group", + NULL +}; + + +// ----- SmartColumnListView ---------------------------------------------------------------- + +const int32 MSG_LIST_DESELECT = 'CLV0'; + +class SmartColumnListView : public ColumnListView +{ + public: + SmartColumnListView(BRect Frame, CLVContainerView** ContainerView, + const char* Name = NULL, uint32 ResizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, + list_view_type Type = B_SINGLE_SELECTION_LIST, + bool hierarchical = false, bool horizontal = true, bool vertical = true, + bool scroll_view_corner = true, border_style border = B_NO_BORDER, + const BFont* LabelFont = be_plain_font) : + ColumnListView(Frame, ContainerView, Name, ResizingMode, flags, Type, hierarchical, + horizontal, vertical, scroll_view_corner, border, LabelFont) + { + container = *ContainerView; + } + + virtual ~SmartColumnListView() + { + } + + void MouseDown(BPoint point) + { + ColumnListView::MouseDown(point); + if (CurrentSelection() < 0) + container->Window()->PostMessage(MSG_LIST_DESELECT); + } + + private: + CLVContainerView *container; +}; + +// ----- FileShareItem ---------------------------------------------------------------------- + +class FileShareItem : public CLVEasyItem +{ + public: + FileShareItem(const char *text0, const char *text1, const char *text2) : + CLVEasyItem(0, false, false, 20.0) + { + // Here we're going to get the mini icon from a specific mime type + BRect bmpRect(0.0, 0.0, 15.0, 15.0); + BBitmap *icon = new BBitmap(bmpRect, B_CMAP8); + + BMimeType mime("application/x-vnd.BeServed-fileshare"); + mime.GetIcon(icon, B_MINI_ICON); + + SetColumnContent(0, icon, 2.0); + SetColumnContent(1, text0); + SetColumnContent(2, text1); + SetColumnContent(3, text2); + } + + ~FileShareItem() + { + } +}; + + +// ----- MilestoneView ----------------------------------------------------- + +class MilestoneView : public BView +{ + public: + MilestoneView(BRect rect, const char *title) : + BView(rect, "MilestoneView", B_FOLLOW_ALL, B_WILL_DRAW) + { + strcpy(heading, title); + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.Teldar-FileSharing"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r; + r.Set(120, 48, 190, 68); + okBtn = new BButton(r, "OKBtn", "OK", new BMessage(MSG_SHARE_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + okBtn->SetEnabled(false); + AddChild(okBtn); + } + + ~MilestoneView() + { + } + + void Draw(BRect rect) + { + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color light = ui_color(B_MENU_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 20); + DrawString(heading); + + SetFont(be_plain_font); + MovePenTo(55, 35); + DrawString(msg); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); + } + + void setText(const char *text, bool done) + { + strcpy(msg, text); + LockLooper(); + Invalidate(Bounds()); + okBtn->SetEnabled(done); + UnlockLooper(); + snooze(200000); + } + + private: + BButton *okBtn; + BBitmap *icon; + char heading[50]; + char msg[256]; +}; + +// ----- MilestonePanel ---------------------------------------------------------------------- + +class MilestonePanel : public BWindow +{ + public: + MilestonePanel(BRect frame, const char *title) : + BWindow(frame, "", B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) + { + BRect r = Bounds(); + milestoneView = new MilestoneView(r, title); + AddChild(milestoneView); + + Show(); + } + + // MessageReceived() + // + void MessageReceived(BMessage *msg) + { + switch (msg->what) + { + case MSG_SHARE_OK: + BWindow::Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } + } + + // setText() + // + void setText(const char *text, bool done) + { + milestoneView->setText(text, done); + } + + private: + MilestoneView *milestoneView; +}; + +// ----- PickUserItem ------------------------------------------------------------ + +class PickUserItem : public CLVEasyItem +{ + public: + PickUserItem(bool group, const char *text0, const char *text1) : + CLVEasyItem(0, false, false, 20.0) + { + BBitmap *icon; + BMessage archive; + size_t size; + + char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), group ? ICON_GROUP_SMALL : ICON_USER_SMALL, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + { + icon = new BBitmap(&archive); + + SetColumnContent(0, icon, 2.0); + SetColumnContent(1, text0); + SetColumnContent(2, text1); + + isGroupItem = group; + } + } + + ~PickUserItem() + { + } + + bool isUser() + { + return !isGroupItem; + } + + bool isGroup() + { + return isGroupItem; + } + + static int CompareItems(const CLVListItem *item1, const CLVListItem *item2, int32 KeyColumn) + { + const char *str1 = ((PickUserItem *) item1)->GetColumnContentText(1); + const char *str2 = ((PickUserItem *) item2)->GetColumnContentText(1); + return strcasecmp(str1, str2); + } + + private: + bool isGroupItem; +}; + +// ----- SecurityView ----------------------------------------------------- + +class SecurityView : public BView +{ + public: + SecurityView(BRect rect) : + BView(rect, "DomainUserView", B_FOLLOW_ALL, B_WILL_DRAW) + { + BMessage archive; + size_t size; + char *bits; + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_PADLOCK_LARGE, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + lockIcon = new BBitmap(&archive); + + BRect r; + r.Set(10, 60, 360, 80); + + mnuMethod = new BPopUpMenu(""); + mnuMethod->AddItem(new BMenuItem("No Authentication Required", NULL)); + mnuMethod->AddItem(new BMenuItem("BeSure Authentication Server", NULL)); +// mnuMethod->AddItem(new BMenuItem("Directory Server (LDAP)", NULL)); + + mnuAccess = new BMenuField(r, "AuthMethod", "Authentication Method:", mnuMethod); + mnuAccess->SetDivider(120); + if (authServerIP) + item = mnuMethod->FindItem("BeSure Authentication Server"); + else + item = mnuMethod->FindItem("No Authentication Required"); + + if (item) + item->SetMarked(true); + AddChild(mnuAccess); + + r.Set(10, 85, 360, 105); + editServer = new BTextControl(r, "ServerName", "Server Name:", authServerName, NULL); + editServer->SetDivider(120); + AddChild(editServer); + + r.Set(210, 115, 280, 135); + okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_DOMUSER_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(290, 115, 360, 135); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_DOMUSER_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); + } + + ~SecurityView() + { + } + + void Draw(BRect rect) + { + BRect r = Bounds(); + BRect iconRect(13.0, 10.0, 45.0, 42.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 17); + DrawString("When users connect to this computer to access shared files,"); + MovePenTo(55, 29); + DrawString("the settings here will be used to determine how those users"); + MovePenTo(55, 41); + DrawString("are authenticated."); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(lockIcon, iconRect); + } + + void UpdateData() + { + struct hostent *ent; + + // If the selected item is to use no authentication, blank out the server name + // and IP address. We'll assume this is the case until we can validate the data + // provided. + authServerName[0] = 0; + authServerIP = 0; + + // Now get the selected authentication method. If it's BeSure, then store the + // server name and obtain its IP address. + BMenuItem *item = mnuMethod->FindMarked(); + if (item) + if (strcmp(item->Label(), "BeSure Authentication Server") == 0) + { + strcpy(authServerName, editServer->Text()); + + ent = gethostbyname(authServerName); + if (ent != NULL) + authServerIP = ntohl(*((unsigned int *) ent->h_addr)); + else + authServerIP = 0; + } + } + + private: + BButton *okBtn; + BPopUpMenu *mnuMethod; + BMenuField *mnuAccess; + BMenuItem *item; + BTextControl *editServer; + BBitmap *lockIcon; +}; + + +// ----- SecurityPanel ---------------------------------------------------------------------- + +class SecurityPanel : public BWindow +{ + public: + SecurityPanel(BRect frame) : + BWindow(frame, "Security", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) + { + BRect r = Bounds(); + infoView = new SecurityView(r); + AddChild(infoView); + + Show(); + } + + // MessageReceived() + // + void MessageReceived(BMessage *msg) + { + switch (msg->what) + { + case MSG_DOMUSER_OK: + infoView->UpdateData(); + BWindow::Quit(); + break; + + case MSG_DOMUSER_CANCEL: + BWindow::Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } + } + + private: + SecurityView *infoView; +}; + +// ----- DomainUserView ----------------------------------------------------- + +class DomainUserView : public BView +{ + public: + DomainUserView(BRect rect) : + BView(rect, "DomainUserView", B_FOLLOW_ALL, B_WILL_DRAW) + { + BMessage archive; + size_t size; + char *bits; + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_LIGHT_LARGE, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + lightIcon = new BBitmap(&archive); + + BRect r; + r.Set(10, 240, 200, 260); + + mnuRights = new BPopUpMenu(""); + mnuRights->AddItem(new BMenuItem("Read-only", NULL)); + mnuRights->AddItem(new BMenuItem("Read-write", NULL)); + + mnuAccess = new BMenuField(r, "AccessRights", "Access Rights:", mnuRights); + mnuAccess->SetDivider(75); + item = mnuRights->FindItem("Read-only"); + if (item) + item->SetMarked(true); + AddChild(mnuAccess); + + r.Set(210, 320, 280, 340); + okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_DOMUSER_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(290, 320, 360, 340); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_DOMUSER_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); + + // Now add the membership list. + CLVContainerView *listContView; + r.Set(13, 48, 360 - B_V_SCROLL_BAR_WIDTH, 230); + listView = new SmartColumnListView(r, &listContView, NULL, B_FOLLOW_ALL_SIDES, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST, + false, false, true, false, B_FANCY_BORDER); + + listView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT)); + listView->AddColumn(new CLVColumn("User or Group", 140.0, CLV_SORT_KEYABLE, 50.0)); + listView->AddColumn(new CLVColumn("Full Name", 160.0, CLV_SORT_KEYABLE)); + + AddUserList(listView); + AddGroupList(listView); + listView->SetSortFunction(PickUserItem::CompareItems); + listView->SortItems(); + + AddChild(listContView); + } + + ~DomainUserView() + { + } + + void Draw(BRect rect) + { + BRect r = Bounds(); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(10, 17); + DrawString("Select a user or group from the list below, select the desired access rights,"); + MovePenTo(10, 29); + DrawString("then click the OK button. Click the Cancel button to abort the selection."); + + MovePenTo(55, 288); + DrawString("When granting write access to a shared volume, you are by"); + MovePenTo(55, 300); + DrawString("definition also granting the ability to rename and delete files."); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + r.Set(13, 275, 45, 307); + DrawBitmap(lightIcon, r); + } + + void AddUserList(ColumnListView* listView) + { + DIR *dir = NULL; + char user[MAX_USERNAME_LENGTH], fullName[MAX_DESC_LENGTH]; + bt_outPacket *outPacket = btRPCPutHeader(BT_CMD_READUSERS, 1, 4); + btRPCPutArg(outPacket, B_INT32_TYPE, &dir, sizeof(int32)); + bt_inPacket *inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket); + if (inPacket) + { + int error, count = 0; + + do + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + memset(user, 0, sizeof(user)); + memset(fullName, 0, sizeof(fullName)); + btRPCGetString(inPacket, user, sizeof(user)); + btRPCGetString(inPacket, fullName, sizeof(fullName)); + listView->AddItem(new PickUserItem(false, user, fullName)); + } + else break; + } while (++count < 80); + + free(inPacket->buffer); + free(inPacket); + } + } + + void AddGroupList(ColumnListView* listView) + { + DIR *dir = NULL; + char group[MAX_USERNAME_LENGTH]; + bt_outPacket *outPacket = btRPCPutHeader(BT_CMD_READGROUPS, 1, 4); + btRPCPutArg(outPacket, B_INT32_TYPE, &dir, sizeof(int32)); + bt_inPacket *inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket); + if (inPacket) + { + int error, count = 0; + + do + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + memset(group, 0, sizeof(group)); + btRPCGetString(inPacket, group, sizeof(group)); + listView->AddItem(new PickUserItem(true, group, "")); + } + else break; + } while (++count < 80); + + free(inPacket->buffer); + free(inPacket); + } + } + + char *GetSelectedUser() + { + if (listView) + { + int index = listView->CurrentSelection(); + if (index >= 0) + { + PickUserItem *item = (PickUserItem *) listView->ItemAt(index); + return ((char *) item->GetColumnContentText(1)); + } + } + + return NULL; + } + + int GetRights() + { + BMenuItem *item = mnuRights->FindMarked(); + if (item) + if (strcmp(item->Label(), "Read-only") == 0) + return BT_RIGHTS_READ; + else if (strcmp(item->Label(), "Read-write") == 0) + return (BT_RIGHTS_READ | BT_RIGHTS_WRITE); + + return 0; + } + + bool isGroup() + { + if (listView) + { + int index = listView->CurrentSelection(); + if (index >= 0) + { + PickUserItem *item = (PickUserItem *) listView->ItemAt(index); + return item->isGroup(); + } + } + + return false; + } + + private: + SmartColumnListView *listView; + BButton *okBtn; + BPopUpMenu *mnuRights; + BMenuField *mnuAccess; + BMenuItem *item; + BBitmap *lightIcon; +}; + + +// ----- DomainUserPanel ---------------------------------------------------------------------- + +class DomainUserPanel : public BWindow +{ + public: + DomainUserPanel(BRect frame, bt_fileShare_t *sharePtr) : + BWindow(frame, "Domain Users", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) + { + share = sharePtr; + + BRect r = Bounds(); + infoView = new DomainUserView(r); + AddChild(infoView); + + Show(); + } + + // MessageReceived() + // + void MessageReceived(BMessage *msg) + { + switch (msg->what) + { + case MSG_DOMUSER_OK: + SaveUserRights(infoView->GetSelectedUser(), infoView->GetRights(), infoView->isGroup()); + BWindow::Quit(); + break; + + case MSG_DOMUSER_CANCEL: + BWindow::Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } + } + + void SaveUserRights(char *user, int rights, bool isGroup) + { + bt_user_rights *ur; + + if (user == NULL || rights == 0) + return; + + for (ur = share->rights; ur; ur = ur->next) + if (strcmp(ur->user, user) == 0) + { + ur->rights = rights; + return; + } + + ur = (bt_user_rights *) malloc(sizeof(bt_user_rights)); + if (ur) + { + ur->user = (char *) malloc(strlen(user) + 1); + if (ur->user) + { + strcpy(ur->user, user); + ur->rights = rights; + ur->isGroup = isGroup; + ur->next = share->rights; + share->rights = ur; + } + else + free(ur); + } + } + + private: + DomainUserView *infoView; + bt_fileShare_t *share; +}; + +// ----- ShareInfoView ----------------------------------------------------- + +class ShareInfoView : public BView +{ + public: + ShareInfoView(BRect rect, bt_fileShare_t *sharePtr) : + BView(rect, "HostInfoView", B_FOLLOW_ALL, B_WILL_DRAW) + { + BMessage archive; + size_t size; + char *bits; + + share = sharePtr; + optionIcon = domainIcon = NULL; + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.BeServed-fileshare"); + mime.GetIcon(icon, B_LARGE_ICON); + + bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_SWITCH_LARGE, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + optionIcon = new BBitmap(&archive); + + bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_DOMAIN_LARGE, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + domainIcon = new BBitmap(&archive); + + BRect r(10, 52, 200, 72); + editName = new BTextControl(r, "ShareName", "Name:", share->name, NULL); + editName->SetDivider(40); + AddChild(editName); + + r.top = 77; + r.bottom = r.top + 20; + r.right = 300; + editPath = new BTextControl(r, "SharePath", "Path:", share->path, NULL); + editPath->SetDivider(40); + AddChild(editPath); + + r.top = 150; + r.bottom = r.top + 15; + chkReadWrite = new BCheckBox(r, "ReadWrite", "Users can make changes to files and folders", NULL); + chkReadWrite->SetValue(share->readOnly ? B_CONTROL_OFF : B_CONTROL_ON); + AddChild(chkReadWrite); + + r.top = 170; + r.bottom = r.top + 15; + chkFollowLinks = new BCheckBox(r, "FollowLinks", "Follow links leading outside the path", NULL); + chkFollowLinks->SetValue(share->followLinks ? B_CONTROL_ON : B_CONTROL_OFF); + chkFollowLinks->SetEnabled(false); + AddChild(chkFollowLinks); + + r.Set(310, 75, 390, 95); + AddChild(new BButton(r, "BrowseBtn", "Browse...", new BMessage(MSG_PATH_BROWSE))); + + r.Set(325, 235, 400, 255); + btnAdd = new BButton(r, "AddBtn", "Add", new BMessage(MSG_PICKUSER_ADD), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + btnAdd->SetEnabled(authServerIP != 0); + AddChild(btnAdd); + + r.Set(325, 265, 400, 285); + btnRemove = new BButton(r, "RemoveBtn", "Remove", new BMessage(MSG_PICKUSER_REMOVE), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + btnRemove->SetEnabled(false); + AddChild(btnRemove); + + // Now add the membership list. + CLVContainerView *listContView; + r.Set(13, 235, 315 - B_V_SCROLL_BAR_WIDTH, 340); + listView = new SmartColumnListView(r, &listContView, NULL, B_FOLLOW_ALL_SIDES, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST, + false, false, true, false, B_FANCY_BORDER); + + listView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT)); + listView->AddColumn(new CLVColumn("User or Group", 150.0, CLV_SORT_KEYABLE, 50.0)); + listView->AddColumn(new CLVColumn("Access", 80.0, CLV_SORT_KEYABLE)); + + listView->SetSelectionMessage(new BMessage(MSG_PICKUSER_SELECT)); + listView->SetInvocationMessage(new BMessage(MSG_LIST_DESELECT)); + + AddUserList(listView); + listView->SetSortFunction(PickUserItem::CompareItems); + listView->SortItems(); + AddChild(listContView); + + r.Set(245, 355, 315, 375); + BButton *okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_SHARE_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(325, 355, 400, 375); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_SHARE_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); + } + + ~ShareInfoView() + { + } + + void Draw(BRect rect) + { + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + DrawString(share->name); + MovePenTo(55, 130); + DrawString("General Options"); + MovePenTo(55, 212); + DrawString("Domain User Access"); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("Use this properties window to define the parameters under which you will"); + MovePenTo(55, 40); + DrawString("allow users to share files on this computer."); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); + + r.Set(13, 113, 45, 145); + DrawBitmap(optionIcon, r); + r.Set(13, 195, 45, 227); + DrawBitmap(domainIcon, r); + + DrawDivider(10, 107, 390); + DrawDivider(10, 193, 390); + } + + void DrawDivider(int left, int top, int width) + { + rgb_color darkGray = { 189, 186, 189, 255 }; + rgb_color lightGray = { 239, 239, 239, 255 }; + BPoint startPt(left, top); + BPoint endPt(left + width, top); + SetHighColor(darkGray); + StrokeLine(startPt, endPt); + startPt.y += 1; + endPt.y += 1; + SetHighColor(lightGray); + StrokeLine(startPt, endPt); + } + + void ItemSelected() + { + if (authServerIP) + btnRemove->SetEnabled(true); + } + + void ItemDeselected() + { + btnRemove->SetEnabled(false); + } + + void AddUserList(ColumnListView* listView) + { + bt_user_rights *ur; + if (share->security != BT_AUTH_NONE) + for (ur = share->rights; ur; ur = ur->next) + { + char access[50]; + access[0] = 0; + if (ur->rights & BT_RIGHTS_READ) + strcat(access, "Read "); + if (ur->rights & BT_RIGHTS_WRITE) + strcat(access, "Write"); + + listView->AddItem(new PickUserItem(ur->isGroup, ur->user, access)); + } + } + + void ResetUserList() + { + FileShareItem *item; + + listView->LockLooper(); + + do + { + item = (FileShareItem *) listView->RemoveItem(int32(0)); + if (item) + delete item; + } while(item); + + AddUserList(listView); + listView->UnlockLooper(); + } + + // setPath() + // + void setPath(const char *path) + { + if (editPath) + { + editPath->LockLooper(); + editPath->SetText(path); + editPath->UnlockLooper(); + } + } + + // RemoveSelectedRights() + // + void RemoveSelectedRights() + { + int curItem; + + listView->LockLooper(); + + curItem = listView->CurrentSelection(); + if (curItem >= 0) + { + FileShareItem *item = (FileShareItem *) listView->ItemAt(curItem); + if (item) + { + bt_user_rights *ur, *lastUR; + const char *user = item->GetColumnContentText(1); + for (ur = share->rights, lastUR = NULL; ur; ur = ur->next) + { + if (strcmp(ur->user, user) == 0) + { + if (lastUR) + lastUR->next = ur->next; + else + share->rights = ur->next; + + free(ur->user); + free(ur); + break; + } + + lastUR = ur; + } + } + + listView->RemoveItem(curItem); + } + + listView->UnlockLooper(); + } + + // updateShare() + // + bool updateShare() + { + BAlert *alert; + char buf[256]; + unsigned int length; + + length = sizeof(share->name); + if (strlen(editName->Text()) > length) + { + sprintf(buf, "The name of this share is too long. Please provide a name that is at most %d characters.", length); + alert = new BAlert("Oops!", buf, "OK"); + return false; + } + + length = sizeof(share->path); + if (strlen(editPath->Text()) > length) + { + sprintf(buf, "The path name is too long. The share path can be at most %d characters.", length); + alert = new BAlert("Oops!", buf, "OK"); + return false; + } + + strcpy(share->name, editName->Text()); + strcpy(share->path, editPath->Text()); + share->readOnly = chkReadWrite->Value() == B_CONTROL_OFF; + share->followLinks = chkFollowLinks->Value() == B_CONTROL_ON; + return true; + } + + private: + SmartColumnListView *listView; + BBitmap *icon, *optionIcon, *domainIcon; + BTextControl *editName; + BTextControl *editPath; + BCheckBox *chkReadWrite; + BCheckBox *chkFollowLinks; + BButton *btnAdd, *btnRemove; + bt_fileShare_t *share; +}; + + +// ----- ShareInfoPanel ---------------------------------------------------------------------- + +class ShareInfoPanel : public BWindow +{ + public: + ShareInfoPanel(BRect frame, bt_fileShare_t *sharePtr, BWindow *parent) : + BWindow(frame, sharePtr->name, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) + { + share = sharePtr; + shareWin = parent; + + BRect r = Bounds(); + infoView = new ShareInfoView(r, share); + AddChild(infoView); + + Show(); + } + + // MessageReceived() + // + void MessageReceived(BMessage *msg) + { + BFilePanel *filePanel; + entry_ref entryRef; + BRect frame; + DomainUserPanel *picker; + status_t status; + + BEntry entry(share->path, false); + entry.GetRef(&entryRef); + + switch (msg->what) + { + case MSG_PATH_BROWSE: + filePanel = new BFilePanel(B_OPEN_PANEL, &be_app_messenger, &entryRef, B_DIRECTORY_NODE, false); + filePanel->Show(); + filePanel->Window()->SetTitle("Shared Folder"); + filePanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select"); + break; + + case MSG_PICKUSER_ADD: + frame = Frame(); + frame.left += 100; + frame.top += 30; + frame.right = frame.left + 370; + frame.bottom = frame.top + 350; + picker = new DomainUserPanel(frame, share); + wait_for_thread(picker->Thread(), &status); + infoView->ResetUserList(); + break; + + case MSG_PICKUSER_REMOVE: + infoView->RemoveSelectedRights(); + break; + + case MSG_PICKUSER_SELECT: + infoView->ItemSelected(); + break; + + case MSG_LIST_DESELECT: //(int32) 'CLV0': + infoView->ItemDeselected(); + break; + + case MSG_SHARE_OK: + if (!infoView->updateShare()) + break; + else + { + BMessage *msg = new BMessage(MSG_SHARE_REFRESH); + msg->AddPointer("share", share); + shareWin->PostMessage(msg); + } + + case MSG_SHARE_CANCEL: + BWindow::Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } + } + + // setPath() + // + void setPath(const char *path) + { + infoView->setPath(path); + } + + private: + ShareInfoView *infoView; + BWindow *shareWin; + bt_fileShare_t *share; +}; + +// ----- FileSharingHeaderView --------------------------------------------------------------- + +class FileSharingHeaderView : public BView +{ + public: + FileSharingHeaderView(BRect rect) : + BView(rect, "FileSharingHeaderView", B_FOLLOW_TOP | B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW) + { + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.Teldar-FileSharing"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r; + r.Set(15, 55, 70, 75); + AddChild(new BButton(r, "NewBtn", "New", new BMessage(MSG_NEW_SHARE))); + + r.Set(80, 55, 135, 75); + editBtn = new BButton(r, "EditBtn", "Edit", new BMessage(MSG_EDIT_SHARE)); + editBtn->SetEnabled(false); + AddChild(editBtn); + + r.Set(145, 55, 210, 75); + removeBtn = new BButton(r, "RemoveBtn", "Remove", new BMessage(MSG_REMOVE_SHARE)); + removeBtn->SetEnabled(false); + AddChild(removeBtn); + + r.Set(337, 55, 412, 75); + AddChild(new BButton(r, "SecurityBtn", "Security", new BMessage(MSG_EDIT_SECURITY))); + } + + ~FileSharingHeaderView() + { + } + + void Draw(BRect rect) + { + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + DrawString("File Sharing Preferences"); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("Normally, remote computers on your network do not have access to files on"); + MovePenTo(55, 40); + DrawString("this computer. You grant them access by explicitly sharing specific folders."); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); + } + + BButton *editBtn; + BButton *removeBtn; + + private: + BBitmap *icon; +}; + +// ----- FileSharingFooterView --------------------------------------------------------------- + +class FileSharingFooterView : public BView +{ + public: + FileSharingFooterView(BRect rect) : + BView(rect, "FileSharingHeaderView", B_FOLLOW_BOTTOM | B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW) + { + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect r; + r.Set(177, 52, 247, 72); + BButton *okBtn = new BButton(r, "SaveBtn", "Save", new BMessage(MSG_SHARE_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(257, 52, 327, 72); + deployBtn = new BButton(r, "DeployBtn", "Deploy", new BMessage(MSG_SHARE_DEPLOY), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + deployBtn->SetEnabled(false); + AddChild(deployBtn); + + r.Set(337, 52, 412, 72); + AddChild(new BButton(r, "CancelBtn", "Close", new BMessage(MSG_SHARE_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); + } + + ~FileSharingFooterView() + { + } + + void Draw(BRect rect) + { + BRect r = Bounds(); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(15, 15); + DrawString("Save your changes to file sharing preferences by clicking the 'Save' button. This"); + MovePenTo(15, 27); + DrawString("will not have an effect on users until you click the 'Deploy' button or manually"); + MovePenTo(15, 39); + DrawString("restart the BeServed file serving application."); + } + + void SetDeployable(bool deployable) + { + deployBtn->SetEnabled(deployable); + } + + private: + BButton *deployBtn; +}; + +// ----- FileSharingWindow ------------------------------------------------------------------- + +class FileSharingWindow : public BWindow +{ + public: + FileSharingWindow() : + BWindow(BRect(50, 50, 475, 460), "File Sharing", B_TITLED_WINDOW, 0) + { + info = NULL; + + BRect r = Bounds(); + + r = Bounds(); + r.bottom = 85; + headerView = new FileSharingHeaderView(r); + AddChild(headerView); + + CLVContainerView *containerView; + r = Bounds(); + r.top = 85; + r.bottom = 325; + + MyColumnListView = new SmartColumnListView(r, &containerView, NULL, B_FOLLOW_ALL_SIDES, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST, + false, false, false, false, B_NO_BORDER); + + MyColumnListView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT)); + MyColumnListView->AddColumn(new CLVColumn("Share Name", 130.0, CLV_SORT_KEYABLE, 50.0)); + MyColumnListView->AddColumn(new CLVColumn("Access", 75.0, CLV_SORT_KEYABLE)); + MyColumnListView->AddColumn(new CLVColumn("Path", 250.0, CLV_SORT_KEYABLE)); + + MyColumnListView->SetSelectionMessage(new BMessage(MSG_SHARE_SELECT)); + MyColumnListView->SetInvocationMessage(new BMessage(MSG_SHARE_INVOKE)); + + initShares(); + AddCLVItems(MyColumnListView); + AddChild(containerView); + + r = Bounds(); + r.top = 325; + footerView = new FileSharingFooterView(r); + AddChild(footerView); + + SetSizeLimits(425, 2000, 250, 2000); + + Show(); + } + + // ~FileSharingWindow() + // + ~FileSharingWindow() + { + be_app->PostMessage(B_QUIT_REQUESTED); + } + + // AddCLVItems() + // + void AddCLVItems(ColumnListView* MyColumnListView) + { + struct stat st; + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + MyColumnListView->AddItem(new FileShareItem(fileShares[i].name, + fileShares[i].readOnly ? "Read-only" : "Read-Write", + stat(fileShares[i].path, &st) == 0 ? fileShares[i].path : "--- Invalid Path ---")); + } + + // MessageReceived() + // + void MessageReceived(BMessage *msg) + { + BRect frame; + bt_fileShare_t *share; + struct stat st; + int32 curItem; + + switch (msg->what) + { + case MSG_EDIT_SHARE: + case MSG_SHARE_INVOKE: + curItem = MyColumnListView->CurrentSelection(); + if (curItem >= 0) + { + FileShareItem *item = (FileShareItem *) MyColumnListView->ItemAt(curItem); + if (item) + { + int index = getShareId((char *) item->GetColumnContentText(1)); + if (index >= 0) + { + fileShares[index].index = curItem; + frame = Frame(); + frame.left += 100; + frame.top += 100; + frame.right = frame.left + 410; + frame.bottom = frame.top + 390; + info = new ShareInfoPanel(frame, &fileShares[index], this); + } + } + } + break; + + case MSG_SHARE_SELECT: + headerView->editBtn->SetEnabled(true); + headerView->removeBtn->SetEnabled(true); + break; + + case MSG_LIST_DESELECT: + headerView->editBtn->SetEnabled(false); + headerView->removeBtn->SetEnabled(false); + break; + + case MSG_NEW_SHARE: + curItem = MyColumnListView->CountItems(); + strcpy(fileShares[curItem].name, "Untitled"); + strcpy(fileShares[curItem].path, "/boot/home"); + fileShares[curItem].readOnly = true; + fileShares[curItem].followLinks = false; + fileShares[curItem].index = curItem; + + frame = Frame(); + frame.left += 100; + frame.top += 100; + frame.right = frame.left + 410; + frame.bottom = frame.top + 390; + info = new ShareInfoPanel(frame, &fileShares[curItem], this); + break; + + case MSG_REMOVE_SHARE: + curItem = MyColumnListView->CurrentSelection(); + if (curItem >= 0) + { + FileShareItem *item = (FileShareItem *) MyColumnListView->ItemAt(curItem); + if (item) + { + curItem = getShareId((char *) item->GetColumnContentText(1)); + if (curItem >= 0) + { + BAlert *alert = new BAlert(fileShares[curItem].name, WARN_REMOVE_SHARE, "Yes", "No"); + alert->SetShortcut(1, B_ESCAPE); + if (alert->Go() == 0) + { + fileShares[curItem].used = false; + MyColumnListView->LockLooper(); + MyColumnListView->RemoveItems(0, MyColumnListView->CountItems()); + AddCLVItems(MyColumnListView); + MyColumnListView->UnlockLooper(); + } + } + } + } + break; + + case MSG_SHARE_REFRESH: + msg->FindPointer("share", (void **) &share); + if (share) + if (share->index >= MyColumnListView->CountItems()) + { + share->used = true; + MyColumnListView->LockLooper(); + MyColumnListView->AddItem(new FileShareItem(share->name, + share->readOnly ? "Read-only" : "Read-Write", + stat(share->path, &st) == 0 ? share->path : "--- Invalid Path ---")); + MyColumnListView->UnlockLooper(); + } + else + refreshShare(share); + + break; + + case MSG_EDIT_SECURITY: + frame = Frame(); + frame.left += 100; + frame.top += 30; + frame.right = frame.left + 370; + frame.bottom = frame.top + 145; + new SecurityPanel(frame); + break; + + case MSG_SHARE_OK: + writeShares(); + footerView->SetDeployable(true); + break; + + case MSG_SHARE_DEPLOY: + footerView->SetDeployable(false); + deployServer(); + break; + + case MSG_SHARE_CANCEL: + Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } + } + + // Quit() + // + void Quit() + { + FileShareItem *item; + + do + { + item = (FileShareItem *) MyColumnListView->RemoveItem(int32(0)); + if (item) + delete item; + } while(item); + + BWindow::Quit(); + } + + // refreshShare() + // + void refreshShare(bt_fileShare_t *share) + { + struct stat st; + int curItem = share->index; + FileShareItem *item = (FileShareItem *) MyColumnListView->ItemAt(curItem); + if (item) + { + int index = getShareId((char *) item->GetColumnContentText(1)); + if (index >= 0) + { + MyColumnListView->LockLooper(); + + item->SetColumnContent(1, fileShares[index].name); + item->SetColumnContent(2, fileShares[index].readOnly ? "Read-only" : "Read-Write"); + item->SetColumnContent(3, stat(fileShares[index].path, &st) == 0 + ? fileShares[index].path + : "--- Invalid Path ---"); + + MyColumnListView->InvalidateItem(index); + MyColumnListView->UnlockLooper(); + } + } + } + + // setPath() + // + void setPath(const char *path) + { + if (info) + info->setPath(path); + } + + private: + // initShares() + // + void initShares() + { + FILE *fp; + char path[B_PATH_NAME_LENGTH], buffer[512]; + int i, length; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + { + fileShares[i].name[0] = 0; + fileShares[i].path[0] = 0; + fileShares[i].used = false; + fileShares[i].readOnly = true; + fileShares[i].followLinks = false; + fileShares[i].index = i; + fileShares[i].next = NULL; + } + + find_directory(B_COMMON_SETTINGS_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/BeServed-Settings"); + + fp = fopen(path, "r"); + if (fp) + { + while (fgets(buffer, sizeof(buffer) - 1, fp)) + { + length = strlen(buffer); + if (length <= 1 || buffer[0] == '#') + continue; + + if (buffer[length - 1] == '\n') + buffer[--length] = 0; + + if (strncmp(buffer, "share ", 6) == 0) + getFileShare(buffer); + else if (strncmp(buffer, "set ", 4) == 0) + getShareProperty(buffer); + else if (strncmp(buffer, "grant ", 6) == 0) + getGrant(buffer); + else if (strncmp(buffer, "authenticate ", 13) == 0) + getAuthenticate(buffer); + } + + fclose(fp); + } + } + + // getFileShare() + // + void getFileShare(const char *buffer) + { + char path[B_PATH_NAME_LENGTH], share[MAX_NAME_LENGTH + 1], *folder; + int i, tok; + + // Skip over SHARE command. + tokPtr = (char *) buffer + (6 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(path, tokBuffer); + tok = getToken(); + if (tok != BT_TOKEN_AS) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + + // Now verify that the share name specified has not already been + // used to share another path. + folder = getSharePath(share); + if (folder) + return; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (!fileShares[i].used) + { + strcpy(fileShares[i].name, share); + strcpy(fileShares[i].path, path); + fileShares[i].used = true; + return; + } + } + + void getShareProperty(const char *buffer) + { + char share[B_FILE_NAME_LENGTH + 1]; + int tok, shareId; + + // Skip over SET command. + tokPtr = (char *) buffer + (4 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + + // Get the index of the share referred to. If the named share cannot be + // found, then abort. + shareId = getShareId(share); + if (shareId < 0) + return; + + tok = getToken(); + if (tok == BT_TOKEN_READWRITE) + fileShares[shareId].readOnly = false; + } + + void getGrant(const char *buffer) + { + char share[MAX_NAME_LENGTH + 1]; + int tok, rights; + bool isGroup = false; + + // Skip over GRANT command. + tokPtr = (char *) buffer + (6 * sizeof(char)); + rights = 0; + + do + { + tok = getToken(); + if (tok == BT_TOKEN_READ) + { + rights |= BT_RIGHTS_READ; + tok = getToken(); + } + else if (tok == BT_TOKEN_WRITE) + { + rights |= BT_RIGHTS_WRITE; + tok = getToken(); + } + } while (tok == BT_TOKEN_COMMA); + + if (tok != BT_TOKEN_ON) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + tok = getToken(); + if (tok != BT_TOKEN_TO) + return; + + tok = getToken(); + if (tok == BT_TOKEN_GROUP) + { + isGroup = true; + tok = getToken(); + } + + if (tok != BT_TOKEN_STRING) + return; + + addUserRights(share, tokBuffer, rights, isGroup); + } + + void getAuthenticate(const char *buffer) + { + struct hostent *ent; + int i, tok; + + // Skip over AUTHENTICATE command. + tokPtr = (char *) buffer + (13 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_WITH) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + // Look up address for given host. + strcpy(authServerName, tokBuffer); + ent = gethostbyname(tokBuffer); + if (ent != NULL) + authServerIP = ntohl(*((unsigned int *) ent->h_addr)); + else + authServerIP = 0; + + // Make all file shares use BeSure authentication. + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + fileShares[i].security = BT_AUTH_BESURE; + } + + void addUserRights(char *share, char *user, int rights, bool isGroup) + { + bt_user_rights *ur; + int shareId; + + shareId = getShareId(share); + if (shareId < 0) + return; + + ur = (bt_user_rights *) malloc(sizeof(bt_user_rights)); + if (ur) + { + ur->user = (char *) malloc(strlen(user) + 1); + if (ur->user) + { + strcpy(ur->user, user); + ur->rights = rights; + ur->isGroup = isGroup; + ur->next = fileShares[shareId].rights; + fileShares[shareId].rights = ur; + } + else + free(ur); + } + } + + char *getSharePath(char *shareName) + { + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (strcasecmp(fileShares[i].name, shareName) == 0) + return fileShares[i].path; + + return NULL; + } + + int getToken() + { + bool quoted = false; + + tokBuffer[0] = 0; + while (*tokPtr && iswhite(*tokPtr)) + tokPtr++; + + if (*tokPtr == ',') + { + *tokPtr++; + return BT_TOKEN_COMMA; + } + else if (*tokPtr == '\"') + { + quoted = true; + tokPtr++; + } + + if (isalnum(*tokPtr) || *tokPtr == '/') + { + int i = 0; + while (isalnum(*tokPtr) || isValid(*tokPtr) || (quoted && *tokPtr == ' ')) + if (i < B_PATH_NAME_LENGTH) + tokBuffer[i++] = *tokPtr++; + else + tokPtr++; + + tokBuffer[i] = 0; + + if (!quoted) + for (i = 0; keywords[i]; i++) + if (strcasecmp(tokBuffer, keywords[i]) == 0) + return ++i; + + if (quoted) + if (*tokPtr != '\"') + return BT_TOKEN_ERROR; + else + tokPtr++; + + return BT_TOKEN_STRING; + } + + return BT_TOKEN_ERROR; + } + + int getShareId(char *shareName) + { + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (strcasecmp(fileShares[i].name, shareName) == 0) + return i; + + return -1; + } + + // writeShares() + // + void writeShares() + { + FILE *fp; + bt_user_rights *ur; + char path[B_PATH_NAME_LENGTH + 1]; + int i; + + find_directory(B_COMMON_SETTINGS_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/BeServed-Settings"); + + fp = fopen(path, "w"); + if (fp) + { + if (authServerIP) + fprintf(fp, "authenticate with %s\n", authServerName); + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + { + fprintf(fp, "share "); + printString(fp, fileShares[i].path); + fprintf(fp, " as "); + printString(fp, fileShares[i].name); + fputc('\n', fp); + + if (!fileShares[i].readOnly) + { + fprintf(fp, "set "); + printString(fp, fileShares[i].name); + fprintf(fp, " read-write\n"); + } + + if (fileShares[i].followLinks) + { + fprintf(fp, "set "); + printString(fp, fileShares[i].name); + fprintf(fp, " promiscuous\n"); + } + + for (ur = fileShares[i].rights; ur; ur = ur->next) + { + int rights = ur->rights; + fprintf(fp, "grant "); + + do + { + if (rights & BT_RIGHTS_READ) + { + fprintf(fp, "read"); + rights &= ~BT_RIGHTS_READ; + } + else if (rights & BT_RIGHTS_WRITE) + { + fprintf(fp, "write"); + rights &= ~BT_RIGHTS_WRITE; + } + + fprintf(fp, "%c", rights > 0 ? ',' : ' '); + } while (rights > 0); + + fprintf(fp, "on "); + printString(fp, fileShares[i].name); + fprintf(fp, " to "); + if (ur->isGroup) + fprintf(fp, "group "); + fprintf(fp, "%s\n", ur->user); + } + } + + fclose(fp); + } + } + + // deployServer() + // + void deployServer() + { + thread_id serverId; + + BRect frame; + frame = Frame(); + frame.left += (frame.right - frame.left) / 2 - 100; + frame.top += (frame.bottom - frame.top) / 2 - 40; + frame.right = frame.left + 200; + frame.bottom = frame.top + 80; + MilestonePanel *statusWin = new MilestonePanel(frame, "Deploying..."); + statusWin->setText("Connecting to the server", false); + + // Find and restart the server. + serverId = find_thread("beserved_server"); + if (serverId != B_NAME_NOT_FOUND) + { + statusWin->setText("Updating configuration", false); + kill(serverId, SIGHUP); + snooze(500000); + } + + statusWin->setText("File sharing deployed", true); + } + + FileSharingHeaderView *headerView; + FileSharingFooterView *footerView; + ColumnListView *MyColumnListView; + ShareInfoPanel *info; +}; + + +// ----- Application ------------------------------------------------------------------------- + +class FileSharingApp : public BApplication +{ + public: + FileSharingApp() : + BApplication("application/x-vnd.Teldar-FileSharing") + { + win = new FileSharingWindow; + } + + ~FileSharingApp() + { + } + + void RefsReceived(BMessage *msg) + { + entry_ref entryRef; + BPath path; + BEntry entry; + + switch (msg->what) + { + case B_REFS_RECEIVED: + msg->FindRef("refs", &entryRef); + entry.SetTo(&entryRef, true); + entry.GetPath(&path); + win->setPath(path.Path()); + break; + + default: + BApplication::RefsReceived(msg); + break; + } + } + + private: + void checkMimeTypes() + { + BMimeType mime; + mime.SetTo("application/x-vnd.Teldar-FileSharing"); + mime.Delete(); + if (!mime.IsInstalled()) + { + mime.Install(); + mime.SetShortDescription("Network File Server"); + mime.SetLongDescription("A network server running BeServed"); +// setMimeIcon(&mime, MYNET_ICON_HOST_LARGE, B_LARGE_ICON); +// setMimeIcon(&mime, MYNET_ICON_HOST_SMALL, B_MINI_ICON); + } + } + + bool setMimeIcon(BMimeType *mime, int32 resourceID, icon_size which) + { + BMessage archive; + size_t size; + char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), resourceID, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + { + BBitmap *icon = new BBitmap(&archive); + mime->SetIcon(icon, which); + return true; + } + + return false; + } + + FileSharingWindow *win; +}; + +// main() +// +int main() +{ + new FileSharingApp; + be_app->Run(); + delete be_app; +} + +// printString() +// +void printString(FILE *fp, const char *str) +{ + if (strchr(str, ' ')) + fprintf(fp, "\"%s\"", str); + else + fprintf(fp, "%s", str); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/FileSharing.proj b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/FileSharing.proj new file mode 100644 index 0000000000..5cd4773d8d Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/FileSharing.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/FileSharing_Bone.proj b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/FileSharing_Bone.proj new file mode 100644 index 0000000000..b9e16df865 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/FileSharing_Bone.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/Resource.rsrc b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/Resource.rsrc new file mode 100644 index 0000000000..1af617c99c Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/Resource.rsrc differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/betalk.h new file mode 100644 index 0000000000..af38d0d926 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +// The different types of network resources supported by BeServed. +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRITNER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 32768 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 128 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int nsid; + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +typedef struct rpcInfo +{ + thread_id rpcThread; + int32 quitXID; + + uint32 serverIP; + int32 serverPort; + int s; +} bt_rpcinfo; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket inPacket; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/rpc.cpp b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/rpc.cpp new file mode 100644 index 0000000000..ba38ddaff2 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/rpc.cpp @@ -0,0 +1,471 @@ +#include "betalk.h" +#include "sysdepdefs.h" +#include "rpc.h" + +#include "signal.h" + + +int btRPCConnect(unsigned int serverIP, int port) +{ + struct sockaddr_in serverAddr; + int session; + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(port); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(serverIP); + + // Create a new socket to receive incoming requests. + session = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (session == INVALID_SOCKET) + return INVALID_SOCKET; + + // Bind that socket to the address constructed above. + if (connect(session, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return INVALID_SOCKET; + + return session; +} + +bool btRPCSend(int session, bt_outPacket *outPacket) +{ + // The XID will be 0. + btRPCPutInt32(outPacket, 0); + btRPCPutChar(outPacket, BT_CMD_TERMINATOR); + + if (btSendMsg(session, outPacket->buffer, outPacket->length, 0) == -1) + return false; + + return true; +} + +bool btRPCCheckSignature(int session) +{ + char signature[20]; + unsigned int sigLen; + + sigLen = strlen(BT_RPC_SIGNATURE); + memset(signature, 0, sigLen); + if (btRecvMsg(session, signature, sigLen, 0) == -1) + return false; + + // Check the signature's validity. + signature[sigLen] = 0; + return (strcmp(signature, BT_RPC_SIGNATURE) == 0); +} + +// btRPCSimpleCall() +// +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket) +{ + struct timeval timeout; + bt_inPacket *inPacket; + fd_set sockSet; + char *buffer; + int session; + int32 xid, length; + + // Establish a connection with the requested server, on the requested port. + // If we can't connect, abort and return a NULL packet. + inPacket = NULL; + session = btRPCConnect(serverIP, port); + if (session == INVALID_SOCKET) + return NULL; + + // If we connected, send the requested RPC packet. If the packet cannot be + // sent, the connection has dropped and we'll abort the call. + if (!btRPCSend(session, outPacket)) + { + closesocket(session); + return NULL; + } + + // Set a reasonable timeout period. Select() is used in leiu of alarm() because + // select() also aborts on error, alarm() effects all threads in a process. + FD_ZERO(&sockSet); + timeout.tv_sec = 8; + timeout.tv_usec = 0; + + // Block in select() waiting for activity. This will block until data is available + // or until a socket error is pending. + FD_SET(session, &sockSet); + select(session + 1, &sockSet, NULL, NULL, &timeout); + + // If our socket has data pending, then read the incoming RPC response packet. + // This should consist of a valid RPC signature, a tranaction ID (xid), the length + // of the variable data, and the data itself. + if (FD_ISSET(session, &sockSet)) + if (btRPCCheckSignature(session)) + { + if (btRecvMsg(session, &xid, sizeof(int32), 0) == -1 || + btRecvMsg(session, &length, sizeof(int32), 0) == -1) + goto abortCall; + + xid = B_LENDIAN_TO_HOST_INT32(xid); + length = B_LENDIAN_TO_HOST_INT32(length); + + // Now allocate a buffer of the appropriate length. If one cannot be + // allocated, we won't be able to store incoming information and the call + // must be aborted. + if (length > 0 && length < BT_RPC_MAX_PACKET_SIZE) + { + buffer = (char *) malloc(length + 1); + if (buffer) + { + // Read the remaining packet contents. The btRecv() function takes + // care of restarting the recv() when signal interrupts occur. It + // will always return -1 on error, even upon orderly shutdown of the peer. + if (btRecvMsg(session, buffer, length, 0) == -1) + { + free(buffer); + goto abortCall; + } + + // Terminate the buffer. + buffer[length] = 0; + + // Allocate a new incoming packet and set its buffer and length. + inPacket = (bt_inPacket *) malloc(sizeof(bt_inPacket)); + if (inPacket) + { + inPacket->buffer = buffer; + inPacket->length = length; + inPacket->offset = 0; + } + else + free(buffer); + } + } + } + + // Execution can naturally lead here or we can jump here from a failed attempt to + // send or receive an RPC packet. The socket is closed and the current incoming + // packet returned, which will be NULL upon failure. +abortCall: + shutdown(session, 2); + close(session); + return inPacket; +} + +int btRecvMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesRead = 0; + do + { + int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags); + if (bytes == -1) + return -1; + + bytesRead += bytes; + } while (bytesRead < dataLen); + + return bytesRead; +} + +// btRecv() +// +int btRecv(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = recv(sock, data, dataLen, flags); + if (bytes == 0) + return -1; + else if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +int btSendMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesSent = 0; + do + { + int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags); + if (bytes == -1) + return -1; + + bytesSent += bytes; + } while (bytesSent < dataLen); + + return bytesSent; +} + +// btSend() +// +int btSend(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = send(sock, data, dataLen, flags); + if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +void btDestroyInPacket(bt_inPacket *packet) +{ + if (packet) + { + if (packet->buffer) + free(packet->buffer); + + free(packet); + } +} + +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length) +{ + bt_outPacket *packet; + + packet = (bt_outPacket *) malloc(sizeof(bt_outPacket)); + if (!packet) + return NULL; + + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + { + free(packet); + return NULL; + } + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + +// btRPCPutChar(packet, BT_RPC_VERSION_HI); +// btRPCPutChar(packet, BT_RPC_VERSION_LO); + btRPCPutInt32(packet, 7 + (8 * argc) + length); + btRPCPutChar(packet, command); + btRPCPutChar(packet, argc); + + return packet; +} + +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length) +{ + btRPCPutInt32(packet, type); + btRPCPutInt32(packet, length); + btRPCPutBinary(packet, data, length); +} + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error, int length) +{ + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + return; + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + btRPCPutInt32(packet, xid); + btRPCPutInt32(packet, 0); + btRPCPutInt32(packet, error); +} + +void btRPCSendAck(int client, bt_outPacket *packet) +{ + if (packet) + if (packet->buffer) + { + *(int32 *)(&packet->buffer[9]) = B_HOST_TO_LENDIAN_INT32(packet->length - 13); + btSendMsg(client, packet->buffer, packet->length, 0); + free(packet->buffer); + } +} + +unsigned char btRPCGetChar(bt_inPacket *packet) +{ + unsigned char value; + + if (packet->offset < packet->length) + value = (unsigned char) packet->buffer[packet->offset]; + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + if (bytes > 0) + memcpy(str, &packet->buffer[packet->offset], bytes); + + str[bytes] = 0; + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return ERANGE; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return ERANGE; + + if (length < bytes) + return ERANGE; + + if (bytes > 0) + memcpy(buffer, &packet->buffer[packet->offset], bytes); + + packet->offset += bytes; + return bytes; +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +int btRPCGetStat(bt_inPacket *packet, struct stat *st) +{ + st->st_dev = 0; + st->st_nlink = btRPCGetInt32(packet); + st->st_uid = btRPCGetInt32(packet); + st->st_gid = btRPCGetInt32(packet); + st->st_size = btRPCGetInt64(packet); + st->st_blksize = btRPCGetInt32(packet); + st->st_rdev = btRPCGetInt32(packet); + st->st_ino = btRPCGetInt64(packet); + st->st_mode = btRPCGetInt32(packet); + st->st_atime = btRPCGetInt32(packet); + st->st_mtime = btRPCGetInt32(packet); + st->st_ctime = btRPCGetInt32(packet); +} + +void btRPCPutStat(bt_outPacket *packet, struct stat *st) +{ + if (packet && st) + { + btRPCPutInt32(packet, (int) st->st_nlink); + btRPCPutInt32(packet, (int) st->st_uid); + btRPCPutInt32(packet, (int) st->st_gid); + btRPCPutInt64(packet, (int64) st->st_size); + btRPCPutInt32(packet, (int) st->st_blksize); + btRPCPutInt32(packet, (int) st->st_rdev); + btRPCPutInt64(packet, (int64) st->st_ino); + btRPCPutInt32(packet, (int) st->st_mode); + btRPCPutInt32(packet, (int) st->st_atime); + btRPCPutInt32(packet, (int) st->st_mtime); + btRPCPutInt32(packet, (int) st->st_ctime); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/rpc.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/rpc.h new file mode 100644 index 0000000000..89c1194d2b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/rpc.h @@ -0,0 +1,25 @@ +// rpc.h + +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket); +int btRPCConnect(unsigned int serverIP, int port); +bool btRPCSend(int session, bt_outPacket *outPacket); +bool btRPCCheckSignature(int session); +void btDestroyInPacket(bt_inPacket *packet); +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error, int length); +void btRPCSendAck(int client, bt_outPacket *packet); +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char *btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +void btRPCGrowPacket(bt_outPacket *packet, int bytes); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/sysdepdefs.h b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/sysdepdefs.h new file mode 100644 index 0000000000..6bb4bd5051 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/FileSharing/sysdepdefs.h @@ -0,0 +1,10 @@ +#ifndef _SYSDEPDEFS_H_ +#define _SYSDEPDEFS_H_ + +#ifdef BONE_VERSION + +#define closesocket(s) close(s) + +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/LICENSE b/src/tests/add-ons/kernel/file_systems/beserved/LICENSE new file mode 100644 index 0000000000..e173ef8ce1 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/LICENSE @@ -0,0 +1,2 @@ +The whole BeServed package is licensed under the MIT license. +It has been open sourced by Teldar Corp. in 2008, and donated to Haiku. diff --git a/src/tests/add-ons/kernel/file_systems/beserved/Menus/MenuTesting.cpp b/src/tests/add-ons/kernel/file_systems/beserved/Menus/MenuTesting.cpp new file mode 100644 index 0000000000..f43fc8a3ec --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/Menus/MenuTesting.cpp @@ -0,0 +1,206 @@ +// File Sharing Preferences Application +// +// FileSharing.cpp +// + +// TODO: +// 1. Make share properties panel modal but still work with file panel + +#include "Application.h" +#include "Window.h" +#include "Alert.h" +#include "CheckBox.h" +#include "Button.h" +#include "TextControl.h" +#include "Menu.h" +#include "MenuBar.h" +#include "PopUpMenu.h" +#include "MenuItem.h" +#include "MenuField.h" +#include "Point.h" +#include "Mime.h" +#include "Roster.h" +#include "Resources.h" + +#define MENU_BAR_HEIGHT 18.0 + +#define MSG_TEST_CANCEL 'TCan' +#define MSG_FILE_NEW 'FNew' +#define MSG_FILE_OPEN 'FOpn' +#define MSG_FILE_SAVE 'FSav' + + +class TestMenuItem : public BMenuItem +{ + public: + TestMenuItem(char *title, BMessage *msg) + : BMenuItem(title, msg) + { + } + + ~TestMenuItem() + { + } + + void DrawContent() + { + Highlight(IsSelected()); + } + + void Highlight(bool flag) + { + rgb_color white = { 255, 255, 255, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color yellow = ui_color(B_WINDOW_TAB_COLOR); + + BPoint point = ContentLocation(); + BMenu *menu = Menu(); + BRect frame = Frame(); + + if (!flag) + { + frame.right = 18; + menu->SetLowColor(gray); + menu->FillRect(frame, B_SOLID_LOW); + frame = Frame(); + frame.left = 18; + } + else + { +// menu->SetLowColor(darkYellow); +// menu->StrokeRect(frame, B_SOLID_LOW); +// frame.InsetBy(1, 1); + } + + menu->SetLowColor(flag ? yellow : white); + menu->FillRect(frame, B_SOLID_LOW); + menu->MovePenTo(point.x + 7, point.y + 10); + menu->DrawString(Label()); + } +}; + +// ----- TestView --------------------------------------------------------------- + +class TestView : public BView +{ + public: + TestView(BRect rect) + : BView(rect, "TestView", B_FOLLOW_BOTTOM | B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW) + { + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect r; + r.Set(337, 52, 412, 72); + AddChild(new BButton(r, "CancelBtn", "Close", new BMessage(MSG_TEST_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); + } + + ~TestView() + { + } + + void Draw(BRect rect) + { + BRect r = Bounds(); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(15, 15); + DrawString(""); + } + + private: + BButton *deployBtn; +}; + +// ----- TestWindow ------------------------------------------------------------------- + +class TestWindow : public BWindow +{ + public: + TestWindow() + : BWindow(BRect(50, 50, 475, 460), "Menu Testing", B_TITLED_WINDOW, 0) + { + BRect r = Bounds(); + + r = Bounds(); + testView = new TestView(r); + AddChild(testView); + + r.bottom = MENU_BAR_HEIGHT; + menuBar = new BMenuBar(r, "MenuBar"); + AddChild(menuBar); + + BMenu *menu = new BMenu("File"); + menuBar->AddItem(menu); + + menu->AddItem(new TestMenuItem("New", new BMessage(MSG_FILE_NEW))); + menu->AddItem(new TestMenuItem("Open", new BMessage(MSG_FILE_OPEN))); + menu->AddItem(new TestMenuItem("Save", new BMessage(MSG_FILE_SAVE))); + + Show(); + } + + // ~TestWindow() + // + ~TestWindow() + { + be_app->PostMessage(B_QUIT_REQUESTED); + } + + // MessageReceived() + // + void MessageReceived(BMessage *msg) + { + switch (msg->what) + { + case MSG_TEST_CANCEL: + Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } + } + + private: + TestView *testView; + BMenuBar *menuBar; +}; + + +// ----- Application ------------------------------------------------------------------------- + +class TestApp : public BApplication +{ + public: + TestApp() + : BApplication("application/x-vnd.Teldar-MenuTesting") + { + win = new TestWindow; + } + + ~TestApp() + { + } + + private: + TestWindow *win; +}; + +// main() +// +int main() +{ + new TestApp; + be_app->Run(); + delete be_app; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/Menus/MenuTesting.proj b/src/tests/add-ons/kernel/file_systems/beserved/Menus/MenuTesting.proj new file mode 100644 index 0000000000..a5533333b8 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/Menus/MenuTesting.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/BlowFish.cpp b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/BlowFish.cpp new file mode 100644 index 0000000000..789eab32a9 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/BlowFish.cpp @@ -0,0 +1,189 @@ +/* blowfish.c */ + +#include "BlowFish.h" +#include "BlowFishTable.h" + +#define N 16 +#define noErr 0 +#define DATAERROR -1 +#define KEYBYTES 8 + +unsigned long F(blf_ctx *bc, unsigned long x) +{ + unsigned long a; + unsigned long b; + unsigned long c; + unsigned long d; + unsigned long y; + + d = x & 0x00FF; + x >>= 8; + c = x & 0x00FF; + x >>= 8; + b = x & 0x00FF; + x >>= 8; + a = x & 0x00FF; + y = bc->S[0][a] + bc->S[1][b]; + y = y ^ bc->S[2][c]; + y = y + bc->S[3][d]; + + return y; +} + +void Blowfish_encipher(blf_ctx *bc, unsigned long *xl, unsigned long *xr) +{ + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = 0; i < N; ++i) + { + Xl = Xl ^ bc->P[i]; + Xr = F(bc, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ bc->P[N]; + Xl = Xl ^ bc->P[N + 1]; + + *xl = Xl; + *xr = Xr; +} + +void Blowfish_decipher(blf_ctx *bc, unsigned long *xl, unsigned long *xr) +{ + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = N + 1; i > 1; --i) + { + Xl = Xl ^ bc->P[i]; + Xr = F(bc, Xl) ^ Xr; + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + } + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ bc->P[1]; + Xl = Xl ^ bc->P[0]; + + *xl = Xl; + *xr = Xr; +} + +short InitializeBlowfish(blf_ctx *bc, unsigned char key[], int keybytes) +{ + short i; + short j; + short k; + unsigned long data; + unsigned long datal; + unsigned long datar; + + /* initialise p & s-boxes without file read */ + for (i = 0; i < N+2; i++) + { + bc->P[i] = bfp[i]; + } + for (i = 0; i < 256; i++) + { + bc->S[0][i] = ks0[i]; + bc->S[1][i] = ks1[i]; + bc->S[2][i] = ks2[i]; + bc->S[3][i] = ks3[i]; + } + + j = 0; + for (i = 0; i < N + 2; ++i) + { + data = 0x00000000; + for (k = 0; k < 4; ++k) + { + data = (data << 8) | key[j]; + j = j + 1; + if (j >= keybytes) + { + j = 0; + } + } + bc->P[i] = bc->P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for (i = 0; i < N + 2; i += 2) + { + Blowfish_encipher(bc, &datal, &datar); + + bc->P[i] = datal; + bc->P[i + 1] = datar; + } + + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 256; j += 2) + { + + Blowfish_encipher(bc, &datal, &datar); + + bc->S[i][j] = datal; + bc->S[i][j + 1] = datar; + } + } + return 0; +} + +void blf_key (blf_ctx *c, unsigned char *k, int len) +{ + InitializeBlowfish(c, k, len); +} + +void blf_enc(blf_ctx *c, unsigned long *data, int blocks) +{ + unsigned long *d; + int i; + + d = data; + for (i = 0; i < blocks; i++) + { + Blowfish_encipher(c, d, d+1); + d += 2; + } +} + +void blf_dec(blf_ctx *c, unsigned long *data, int blocks) +{ + unsigned long *d; + int i; + + d = data; + for (i = 0; i < blocks; i++) + { + Blowfish_decipher(c, d, d+1); + d += 2; + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/BlowFish.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/BlowFish.h new file mode 100644 index 0000000000..cb2d4ec01b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/BlowFish.h @@ -0,0 +1,35 @@ +/* blowfish.h */ + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +#define UWORD32 unsigned long +#define UBYTE08 unsigned char + +#define MAXKEYBYTES 56 /* 448 bits */ + +typedef struct +{ + unsigned long S[4][256], P[18]; +} blf_ctx; + +unsigned long F(blf_ctx *, unsigned long x); +void Blowfish_encipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +void Blowfish_decipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +short InitializeBlowfish(blf_ctx *, unsigned char key[], int keybytes); + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE void blf_enc(blf_ctx *c, unsigned long *data, int blocks); +_IMPEXP_BESURE void blf_dec(blf_ctx *c, unsigned long *data, int blocks); +_IMPEXP_BESURE void blf_key(blf_ctx *c, unsigned char *key, int len); + +#ifdef __cplusplus +} +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/BlowFishTable.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/BlowFishTable.h new file mode 100644 index 0000000000..3547ee1d19 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/BlowFishTable.h @@ -0,0 +1,280 @@ +/* bf_tab.h: Blowfish P-box and S-box tables */ + + +static UWORD32 bfp[] = +{ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b, +}; + +static UWORD32 ks0[] = +{ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + }; + static UWORD32 ks1[]= + { + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 +}; +static UWORD32 ks2[] = +{ + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 +}; +static UWORD32 ks3[] = +{ + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Drive16x16.gif b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Drive16x16.gif new file mode 100644 index 0000000000..72226d4027 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Drive16x16.gif differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Drive32x32.gif b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Drive32x32.gif new file mode 100644 index 0000000000..f1dd65d0d9 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Drive32x32.gif differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/SOURCE.GIF b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/SOURCE.GIF new file mode 100644 index 0000000000..151f12aa08 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/SOURCE.GIF differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Server16x16.gif b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Server16x16.gif new file mode 100644 index 0000000000..03227d477c Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Server16x16.gif differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Server32x32.gif b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Server32x32.gif new file mode 100644 index 0000000000..c7229898f1 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/Server32x32.gif differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/ServerBitmap.bmp b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/ServerBitmap.bmp new file mode 100644 index 0000000000..ddc522145d Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/ServerBitmap.bmp differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/ShareBitmap b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/ShareBitmap new file mode 100644 index 0000000000..05e72485ee Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/ShareBitmap differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/ZIP.GIF b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/ZIP.GIF new file mode 100644 index 0000000000..23248858f4 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/ZIP.GIF differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/index.html b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/index.html new file mode 100644 index 0000000000..835d61626b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/index.html @@ -0,0 +1,40 @@ + + + + IconListItem v1.1 + + + + + + +

+ + + +

IconListItem v1.1

+



Icons in a BOutlineListViewicon +

Source code for a class that will quickly and easily display an icon of your choice and a label into a ListItem.

+

My main purpose was to be able to add icons into a BOutlineListView.

+

A sample project will show you how to use this class.

+
+

08/06/99 Version 1.1 : Fixes for some memory leaks

+

07/30/99 Version 1.0 : Initial release

+ + DownloadPPC/Intel Download +
+ + + +


+ + +
+ This page is copyright © 1999 Fabien Fulhaber. + The icons used herein are the property of Be, Inc. and are used by permission. +
+
+ + + + \ No newline at end of file diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/screenshot.png b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/screenshot.png new file mode 100644 index 0000000000..da8f53c2e5 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/DOC/screenshot.png differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/IconListItem.cpp b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/IconListItem.cpp new file mode 100644 index 0000000000..522c3f7997 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/IconListItem.cpp @@ -0,0 +1,113 @@ +//------------------------------------------------------------------------------ +// IconListItem.cpp +//------------------------------------------------------------------------------ +// A ListItem implementation that displays an icon and its label. +// +// IconListItem implementation Copyright (C) 1999 Fabien Fulhaber +// Special thanks to Brendan Allen for his help. +// Thanks to NPC community (http://www.beroute.tzo.com/npc/). +// This code is free to use in any way so long as the credits above remain intact. +// This code carries no warranties or guarantees of any kind. Use at your own risk. +//------------------------------------------------------------------------------ +// I N C L U D E S +//------------------------------------------------------------------------------ + +#include "IconListItem.h" + +//------------------------------------------------------------------------------ +// I M P L E M E N T A T I O N +//------------------------------------------------------------------------------ + +IconListItem::IconListItem(BBitmap *mini_icon,char *text, uint32 data, int level, bool expanded) : + BListItem(level,expanded) +{ + if (mini_icon) + { + BRect rect(0.0, 0.0, 15.0, 15.0); + icon = new BBitmap(rect, B_CMAP8); + + if ((mini_icon->BytesPerRow() == icon->BytesPerRow()) && + (mini_icon->BitsLength() == icon->BitsLength())) + memcpy(icon->Bits(), mini_icon->Bits(), mini_icon->BitsLength()); + else + delete icon; + } + + SetHeight(18.0); + label.SetTo(text); + extra = data; + BFont font(be_plain_font); + float width_of_item = font.StringWidth(text); + SetWidth(width_of_item); +} + +IconListItem::~IconListItem() +{ + if (icon) + { + delete icon; + icon = NULL; + } +} + +void IconListItem::DrawItem(BView *owner, BRect frame, bool complete) +{ + rgb_color color; + + if (icon) + { + frame.left += 18; + frame.top += 3; + frame.bottom = frame.top + 10; + BRect rect(frame.left - 15.0, frame.top - 2.0, frame.left, frame.top + 13.0); + owner->MovePenTo(0, frame.top); + if (IsSelected()) + { + owner->SetHighColor(255, 255, 255, 255); + owner->FillRect(rect); + owner->SetDrawingMode(B_OP_INVERT); + owner->DrawBitmap(icon, rect); + owner->SetDrawingMode(B_OP_ALPHA); + owner->SetHighColor(0, 0, 0, 180); + owner->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + owner->DrawBitmap(icon, rect); + } + else + { + owner->SetDrawingMode(B_OP_OVER); + owner->DrawBitmap(icon, rect); + } + + owner->SetDrawingMode(B_OP_OVER); + } + + frame.left += 5.0; + frame.top += 1.0; + frame.right = frame.left + Width() + 1.0; + frame.bottom += 3.0; + if (IsSelected() || complete) + { + if (IsSelected()) + color.red = color.green = color.blue = color.alpha = 0; + else + color=owner->ViewColor(); + + owner->SetHighColor(color); + owner->FillRect(frame); + } + + float middle = (frame.bottom + frame.top) / 2.0; + owner->MovePenTo(frame.left + 1.0, (middle + 4.0)); + if (IsSelected()) + color.red = color.green = color.blue = color.alpha = 255; + else + color.red = color.green = color.blue = color.alpha = 0; + + owner->SetHighColor(color); + owner->DrawString(label.String()); +} + +void IconListItem::Update(BView *owner, const BFont *font) +{ +} +//---------------------------------------------------------- IconListMenu.cpp -- diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/IconListItem.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/IconListItem.h new file mode 100644 index 0000000000..b4662e133c --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/IconListItem.h @@ -0,0 +1,77 @@ +//------------------------------------------------------------------------------ +// IconListItem.h +//------------------------------------------------------------------------------ +// A ListItem implementation that displays an icon and its label. +// +// IconListItem implementation Copyright (C) 1999 Fabien Fulhaber +// Special thanks to Brendan Allen for his help. +// Thanks to NPC community (http://www.beroute.tzo.com/npc/). +// This code is free to use in any way so long as the credits above remain intact. +// This code carries no warranties or guarantees of any kind. Use at your own risk. +//------------------------------------------------------------------------------ + +#ifndef _ICON_LIST_ITEM_H_ +#define _ICON_LIST_ITEM_H_ + +//------------------------------------------------------------------------------ +// I N C L U D E S +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// D E C L A R A T I O N S +//------------------------------------------------------------------------------ + +const int32 MSG_LIST_DESELECT = 'CLV0'; + +class IconListView : public BListView +{ + public: + IconListView(BRect frame, const char *name, + list_view_type type = B_SINGLE_SELECTION_LIST, + uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS) + : BListView(frame, name, type, resizingMode, flags) + { + } + + ~IconListView() + { + } + + void MouseDown(BPoint point) + { + BListView::MouseDown(point); + if (CurrentSelection() < 0) + Window()->PostMessage(MSG_LIST_DESELECT); + } +}; + +class IconListItem : public BListItem +{ + public: + IconListItem(BBitmap *mini_icon, char *text, uint32 data, int level, bool expanded); + const char *GetItemText() { return label.String(); } + const uint32 GetItemData() { return extra; } + + virtual ~IconListItem(); + virtual void DrawItem(BView *owner, BRect frame, bool complete = false); + virtual void Update(BView *owner, const BFont *font); + + private: + BRect bounds; + BBitmap *icon; + BString label; + uint32 extra; +}; + +#endif +//------------------------------------------------------------ IconListMenu.h -- diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/InstallPrinter.cpp b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/InstallPrinter.cpp new file mode 100644 index 0000000000..15315e9c37 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/InstallPrinter.cpp @@ -0,0 +1,335 @@ +#include "Mime.h" +#include "TypeConstants.h" +#include "Application.h" +#include "InterfaceDefs.h" +#include "TranslationUtils.h" +#include "Button.h" +#include "Errors.h" +#include "Window.h" +#include "Alert.h" +#include "TextControl.h" +#include "FindDirectory.h" +#include "Directory.h" +#include "Roster.h" +#include "Bitmap.h" +#include "OS.h" +#include "PrintJob.h" + +// POSIX includes +#include "errno.h" +#include "malloc.h" +#include "signal.h" + +#include "InstallPrinter.h" + +#define PRT_SERVER_SIGNATURE "application/x-vnd.Be-PSRV" + +#define PRT_ATTR_MIMETYPE "application/x-vnd.Be.printer\0" +#define PRT_ATTR_STATE "free\0" +#define PRT_ATTR_TRANSPORT "beserved\0" +#define PRT_ATTR_TRANSPORTADDR "local\0" +#define PRT_ATTR_CONNECTION "local\0" +#define PRT_ATTR_COMMENTS "\0" + +char *printerTypes[] = { "HP PCL3 LaserJet Compatible\0" }; + + +// ----- InstallPrinterView ----------------------------------------------------- + +InstallPrinterView::InstallPrinterView(BRect rect, char *host, char *printer) + : BView(rect, "InstallPrinterView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + strcpy(this->host, host); + strcpy(this->printer, printer); + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.Be.printer"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r(55, 50, 250, 65); + chkDefault = new BCheckBox(r, "Default", "Make this my default printer", NULL); + chkDefault->SetValue(B_CONTROL_ON); + AddChild(chkDefault); + + r.top = 70; + r.bottom = r.top + 20; + chkTestPage = new BCheckBox(r, "TestPage", "Print a test page", NULL); + chkTestPage->SetValue(B_CONTROL_OFF); + chkTestPage->SetEnabled(false); + AddChild(chkTestPage); + + r.Set(140, 105, 260, 125); + BButton *okBtn = new BButton(r, "OkayBtn", "Configure Printer", new BMessage(MSG_INSTALL_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(270, 105, 340, 125); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_INSTALL_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); +} + +InstallPrinterView::~InstallPrinterView() +{ +} + +void InstallPrinterView::Draw(BRect rect) +{ + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + char msg[512]; + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + DrawString("Configure this Printer?"); + + sprintf(msg, "'%s' on computer '%s?'", printer, host); + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("Would you like to configure your computer to print to printer"); + MovePenTo(55, 40); + DrawString(msg); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); +} + + +// ----- InstallPrinterPanel ---------------------------------------------------------------------- + +InstallPrinterPanel::InstallPrinterPanel(BRect frame, char *host, char *printer) + : BWindow(frame, "New Printer", B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) +{ + cancelled = false; + + BRect r = Bounds(); + installView = new InstallPrinterView(r, host, printer); + AddChild(installView); + + Show(); +} + +InstallPrinterPanel::~InstallPrinterPanel() +{ +} + +// MessageReceived() +// +void InstallPrinterPanel::MessageReceived(BMessage *msg) +{ + switch (msg->what) + { + case MSG_INSTALL_OK: + cancelled = false; + defaultPrinter = installView->isDefault(); + sendTestPage = installView->printTestPage(); + BWindow::Quit(); + break; + + case MSG_INSTALL_CANCEL: + cancelled = true; + BWindow::Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } +} + +// CreatePrinter() +// +bool InstallPrinterPanel::CreatePrinter(char *printer, char *host, int type, char *user, char *password) +{ + char path[B_PATH_NAME_LENGTH], msg[B_PATH_NAME_LENGTH + 256]; + + // Create the printer spooling folder. If it cannot be created, we'll have to abort. + find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/printers/"); + strcat(path, printer); + if (create_directory(path, S_IRWXU | S_IRWXG | S_IRWXO) != B_OK) + { + sprintf(msg, "A printer spooling folder, %s, could not be created.", path); + BAlert *alert = new BAlert("", msg, "OK"); + alert->Go(); + return false; + } + + // Now set the necessary attributes for the printing system to work. This includes + // standard BeOS attributes, such as BEOS:TYPE and Driver Name, but also includes those + // specific to BeServed, such as "server," which identifies the remote host. + int file = open(path, O_RDONLY); + if (file >= 0) + { + fs_write_attr(file, "BEOS:TYPE", B_STRING_TYPE, 0, PRT_ATTR_MIMETYPE, strlen(PRT_ATTR_MIMETYPE) + 1); + fs_write_attr(file, "Driver Name", B_STRING_TYPE, 0, printerTypes[type], strlen(printerTypes[type]) + 1); + fs_write_attr(file, "Printer Name", B_STRING_TYPE, 0, printer, strlen(printer) + 1); + fs_write_attr(file, "state", B_STRING_TYPE, 0, PRT_ATTR_STATE, strlen(PRT_ATTR_STATE) + 1); + fs_write_attr(file, "transport", B_STRING_TYPE, 0, PRT_ATTR_TRANSPORT, strlen(PRT_ATTR_TRANSPORT) + 1); + fs_write_attr(file, "transport_address", B_STRING_TYPE, 0, PRT_ATTR_TRANSPORTADDR, strlen(PRT_ATTR_TRANSPORTADDR) + 1); + fs_write_attr(file, "connection", B_STRING_TYPE, 0, PRT_ATTR_CONNECTION, strlen(PRT_ATTR_CONNECTION) + 1); + fs_write_attr(file, "Comments", B_STRING_TYPE, 0, PRT_ATTR_COMMENTS, strlen(PRT_ATTR_COMMENTS) + 1); + fs_write_attr(file, "server", B_STRING_TYPE, 0, host, strlen(host) + 1); + fs_write_attr(file, "user", B_STRING_TYPE, 0, user, strlen(user) + 1); + fs_write_attr(file, "password", B_STRING_TYPE, 0, password, BT_AUTH_TOKEN_LENGTH + 1); + close(file); + } + +// if (!NotifyPrintServer(printer, type)) + RestartPrintServer(); + + return true; +} + +void InstallPrinterPanel::RestartPrintServer() +{ + app_info appInfo; + + if (be_roster->GetAppInfo(PRT_SERVER_SIGNATURE, &appInfo) == B_OK) + { + int retries = 0; + kill(appInfo.thread, SIGTERM); + while (be_roster->IsRunning(PRT_SERVER_SIGNATURE) && retries++ < 5) + sleep(1); + } + + be_roster->Launch(PRT_SERVER_SIGNATURE); +} + +void InstallPrinterPanel::SetDefaultPrinter(char *printer) +{ + FILE *fp; + char path[B_PATH_NAME_LENGTH]; + int i; + + // Create the printer spooling folder. If it cannot be created, we'll have to abort. + find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/printer_data"); + + fp = fopen(path, "wb"); + if (fp) + { + fputs(printer, fp); + for (i = strlen(printer); i < 256; i++) + fputc('\0', fp); + + fclose(fp); + } +} + +bool InstallPrinterPanel::NotifyPrintServer(char *printer, int type) +{ + BMessage msg('selp'); + BMessenger msgr; + + if (!GetPrintServerMessenger(msgr)) + return false; + + msg.AddString("driver", printerTypes[type]); + msg.AddString("transport", PRT_ATTR_TRANSPORT); + msg.AddString("transport path", PRT_ATTR_TRANSPORTADDR); + msg.AddString("printer name", printer); + msg.AddString("connection", PRT_ATTR_CONNECTION); + msgr.SendMessage(&msg); + return true; +} + +bool InstallPrinterPanel::GetPrintServerMessenger(BMessenger &msgr) +{ + if (!be_roster->IsRunning(PRT_SERVER_SIGNATURE)) + be_roster->Launch(PRT_SERVER_SIGNATURE); + + msgr = BMessenger(PRT_SERVER_SIGNATURE); + return msgr.IsValid(); +} + + +void InstallPrinterPanel::TestPrinter(char *printer) +{ + char *jobName = new char [strlen(printer) + 20]; + if (!jobName) + return; + + sprintf(jobName, "%s Test Page", printer); + BPrintJob job(jobName); + + if (job.ConfigPage() == B_OK) + if (job.ConfigJob() == B_OK) + { + BRect printableRect = job.PrintableRect(); + BPoint startPoint(printableRect.left, printableRect.top); + TestPrintView *testView = new TestPrintView(printableRect); + + job.BeginJob(); + job.DrawView(testView, printableRect, startPoint); + job.SpoolPage(); + job.CommitJob(); + + delete testView; + } + + delete jobName; +} + +// ----- TestPrintView ------------------------------------------------------------------------ + +TestPrintView::TestPrintView(BRect rect) + : BView(rect, "TestPrintView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + BMessage archive; + size_t size; + char *bits; + + rgb_color white = { 255, 255, 255, 255 }; + SetViewColor(white); + +// bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), BMP_TESTPAGE_LOGO, &size); +// if (bits) +// if (archive.Unflatten(bits) == B_OK) +// beServedIcon = new BBitmap(&archive); +} + +TestPrintView::~TestPrintView() +{ +} + +void TestPrintView::Draw(BRect rect) +{ + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color white = { 255, 255, 255, 255 }; + + SetViewColor(white); + SetLowColor(white); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + DrawString(""); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("This test page has been sent to your printer by request. By reading this information, you are confirming"); + MovePenTo(55, 40); + DrawString("that this printer is communicating correctly with the computer from which this test was sent."); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(beServedIcon, iconRect); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/InstallPrinter.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/InstallPrinter.h new file mode 100644 index 0000000000..4f3600abb3 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/InstallPrinter.h @@ -0,0 +1,79 @@ +#include "Window.h" +#include "View.h" +#include "Button.h" +#include "CheckBox.h" +#include "Bitmap.h" + +#include "betalk.h" + +const uint32 MSG_INSTALL_OK = 'InOK'; +const uint32 MSG_INSTALL_CANCEL = 'InCn'; + + +// ----- InstallPrinterView ----------------------------------------------------- + +class InstallPrinterView : public BView +{ + public: + InstallPrinterView(BRect rect, char *host, char *printer); + ~InstallPrinterView(); + + void Draw(BRect rect); + + bool isDefault() { return chkDefault->Value() == B_CONTROL_ON; } + bool printTestPage() { return chkTestPage->Value() == B_CONTROL_ON; } + + private: + BBitmap *icon; + BButton *okBtn; + BCheckBox *chkDefault; + BCheckBox *chkTestPage; + char host[B_FILE_NAME_LENGTH]; + char printer[B_FILE_NAME_LENGTH]; +}; + + +// ----- InstallPrinterPanel ---------------------------------------------------------------------- + +class InstallPrinterPanel : public BWindow +{ + public: + InstallPrinterPanel(BRect frame, char *host, char *printer); + ~InstallPrinterPanel(); + + bool CreatePrinter(char *printer, char *host, int type, char *user, char *password); + void RestartPrintServer(); + void SetDefaultPrinter(char *printer); + void TestPrinter(char *printer); + + void MessageReceived(BMessage *msg); + bool IsCancelled() { return cancelled; } + bool isDefault() { return defaultPrinter; } + bool printTestPage() { return sendTestPage; } + + sem_id installSem; + + private: + bool NotifyPrintServer(char *printer, int type); + bool GetPrintServerMessenger(BMessenger &msgr); + + InstallPrinterView *installView; + bool cancelled; + bool defaultPrinter; + bool sendTestPage; +}; + + +// ----- TestPrintView ----------------------------------------------------- + +class TestPrintView : public BView +{ + public: + TestPrintView(BRect rect); + ~TestPrintView(); + + void Draw(BRect rect); + + private: + BBitmap *beServedIcon; +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/LoginPanel.cpp b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/LoginPanel.cpp new file mode 100644 index 0000000000..7ea031daac --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/LoginPanel.cpp @@ -0,0 +1,147 @@ +#include "Mime.h" +#include "TypeConstants.h" +#include "Application.h" +#include "InterfaceDefs.h" +#include "TranslationUtils.h" +#include "Button.h" +#include "Errors.h" +#include "Window.h" +#include "TextControl.h" +#include "Roster.h" +#include "Bitmap.h" +#include "OS.h" + +// POSIX includes +#include "errno.h" +#include "malloc.h" + +#include "LoginPanel.h" +#include "md5.h" + +// To create: +// BRect frame2(100, 150, 350, 290); +// LoginPanel *login = new LoginPanel(frame2); + + +// ----- LoginView ----------------------------------------------------- + +LoginView::LoginView(BRect rect) + : BView(rect, "LoginView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.Teldar-FileSharing"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r(10, 52, 240, 72); + user = new BTextControl(r, "User", "User:", "", NULL); + user->SetDivider(55); + AddChild(user); + + r.top = 77; + r.bottom = r.top + 20; + password = new BTextControl(r, "Password", "Password:", "", NULL); + password->SetDivider(55); + password->TextView()->HideTyping(true); + AddChild(password); + + r.Set(90, 105, 160, 125); + BButton *okBtn = new BButton(r, "OkayBtn", "Login", new BMessage(MSG_LOGIN_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(170, 105, 240, 125); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_LOGIN_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); +} + +LoginView::~LoginView() +{ +} + +void LoginView::Draw(BRect rect) +{ + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + DrawString("Login Required"); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("The resource you've specified requires"); + MovePenTo(55, 40); + DrawString("permission to access it."); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); +} + + +// ----- LoginPanel ---------------------------------------------------------------------- + +LoginPanel::LoginPanel(BRect frame) + : BWindow(frame, "Login", B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) +{ + user[0] = password[0] = 0; + cancelled = false; + + BRect r = Bounds(); + loginView = new LoginView(r); + AddChild(loginView); + + Show(); +} + +LoginPanel::~LoginPanel() +{ +} + +// MessageReceived() +// +void LoginPanel::MessageReceived(BMessage *msg) +{ + switch (msg->what) + { + case MSG_LOGIN_OK: + cancelled = false; + safeStringCopy(user, loginView->GetUser(), sizeof(user)); + safeStringCopy(password, loginView->GetPassword(), sizeof(password)); + md5EncodeString(password, md5passwd); + BWindow::Quit(); + break; + + case MSG_LOGIN_CANCEL: + cancelled = true; + BWindow::Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } +} + +void safeStringCopy(char *dest, const char *source, int destSize) +{ + int length = strlen(source); + if (length >= destSize) + length = destSize - 1; + + strncpy(dest, source, length); + dest[length] = 0; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/LoginPanel.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/LoginPanel.h new file mode 100644 index 0000000000..670ef67ccb --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/LoginPanel.h @@ -0,0 +1,58 @@ +#include "Window.h" +#include "View.h" +#include "TextControl.h" +#include "Button.h" +#include "Bitmap.h" + +#include "betalk.h" + +const uint32 MSG_LOGIN_OK = 'LgOK'; +const uint32 MSG_LOGIN_CANCEL = 'LgCn'; + + +// ----- LoginView ----------------------------------------------------- + +class LoginView : public BView +{ + public: + LoginView(BRect rect); + ~LoginView(); + + void Draw(BRect rect); + + const char *GetUser() { return user->Text(); } + const char *GetPassword() { return password->Text(); } + + private: + BBitmap *icon; + BTextControl *user; + BTextControl *password; +}; + + +// ----- LoginPanel ---------------------------------------------------------------------- + +class LoginPanel : public BWindow +{ + public: + LoginPanel(BRect frame); + ~LoginPanel(); + + void MessageReceived(BMessage *msg); + bool IsCancelled() { return cancelled; } + + char user[MAX_NAME_LENGTH]; + char password[MAX_NAME_LENGTH]; + char md5passwd[MAX_NAME_LENGTH]; + + sem_id loginSem; + + private: + LoginView *loginView; + bool cancelled; +}; + + +// ----- Utilities ---------------------------------------------------------------------- + +void safeStringCopy(char *dest, const char *source, int destSize); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyDriveView.cpp b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyDriveView.cpp new file mode 100644 index 0000000000..0e5027fdab --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyDriveView.cpp @@ -0,0 +1,83 @@ +#include "Mime.h" +#include "TypeConstants.h" +#include "Application.h" +#include "InterfaceDefs.h" +#include "TranslationUtils.h" +#include "StatusBar.h" +#include "Button.h" +#include "Alert.h" +#include "Errors.h" +#include "OS.h" + +// POSIX includes +#include "errno.h" +#include "malloc.h" +#include "socket.h" +#include "signal.h" +#include "netdb.h" + +#include "IconListItem.h" +#include "MyDriveView.h" + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BTN_MOUNT_MSG 'bmnt' +#define BTN_INCREASE_MSG 'binc' +#define BTN_SETTINGS_MSG 'bset' + + +MyDriveView::MyDriveView(BRect rect) + : BView(rect, "MyDriveView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + // Here we're going to get the mini icon from a specific mime type +// BRect bmpRect(0.0, 0.0, 15.0, 15.0); +// icon = new BBitmap(bmpRect, B_CMAP8); + SetDriveSpace(0, 0, 0); + + BRect progRect(5.0, 30.0, 225.0, 42.0); + barFull = new BStatusBar(progRect, "barFull"); + barFull->SetBarHeight(13.0); + AddChild(barFull); + + BRect mntRect(5.0, 65.0, 70.0, 80.0); + BButton *btnMount = new BButton(mntRect, "btnMount", "Mount", new BMessage(BTN_MOUNT_MSG)); + AddChild(btnMount); + + BRect incRect(75.0, 65.0, 190.0, 80.0); + BButton *btnIncrease = new BButton(incRect, "btnIncrease", "Increase Space", new BMessage(BTN_INCREASE_MSG)); + AddChild(btnIncrease); +} + +MyDriveView::~MyDriveView() +{ +} + +void MyDriveView::Draw(BRect rect) +{ + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetHighColor(black); + + SetFont(be_bold_font); + SetFontSize(10); + MoveTo(5, 10); + DrawString("Online Storage Details"); + + SetFont(be_plain_font); + MoveTo(5, 20); +// DrawString(msg); +} + +void MyDriveView::SetDriveSpace(int percentFull, int files, int folders) +{ +// barFull->Update(percentFull); +// sprintf(msg, "Your online storage is %d%% full, containing %d files in %d folders", +// percentFull, files, folders); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyDriveView.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyDriveView.h new file mode 100644 index 0000000000..11386b9b05 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyDriveView.h @@ -0,0 +1,27 @@ +#ifndef _MYDRIVEVIEW_H_ +#define _MYDRIVEVIEW_H_ + +#include +#include +#include +#include +#include + +#include + + +class MyDriveView : public BView +{ + public: + MyDriveView(BRect rect); + ~MyDriveView(); + + void Draw(BRect rect); + void SetDriveSpace(int percentFull, int files, int folders); + + private: + BStatusBar *barFull; + char msg[100]; +}; + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetApp.cpp b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetApp.cpp new file mode 100644 index 0000000000..47667a6f5f --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetApp.cpp @@ -0,0 +1,1027 @@ +// MyNetApp.cpp + +#include "Application.h" +#include "Resources.h" +#include "TabView.h" +#include "Alert.h" +#include "Menu.h" +#include "MenuBar.h" +#include "MenuItem.h" +#include "Button.h" +#include "FilePanel.h" +#include "FindDirectory.h" +#include "TextControl.h" +#include "Path.h" +#include "Mime.h" +#include "Roster.h" + +#include "assert.h" +#include "unistd.h" +#include "socket.h" +#include "netdb.h" +#include "time.h" + +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +#include "betalk.h" +#include "besure_auth.h" +#include "rpc.h" +#include "BlowFish.h" +#include "MyNetView.h" +#include "MyDriveView.h" +#include "IconListItem.h" +#include "btAddOn.h" +#include "LoginPanel.h" +#include "InstallPrinter.h" + +#ifndef BONE_VERSION +#include "ksocket_internal.h" +#else +#include "arpa/inet.h" +#endif + +#define BT_HOST_PATH "/boot/home/Connections" +#define IsValid(s) (strcmp((s), ".") && strcmp((s), "..")) + +#define MYNET_ICON_HOST_LARGE 101 +#define MYNET_ICON_SHARE_LARGE 102 +#define MYNET_ICON_HOST_SMALL 103 +#define MYNET_ICON_SHARE_SMALL 104 +#define MYNET_ICON_INETHOST_LARGE 105 +#define MYNET_ICON_INETHOST_SMALL 106 + + +// ----- SmartColumnListView ---------------------------------------------------------------- + +class SmartColumnListView : public ColumnListView +{ + public: + SmartColumnListView(BRect Frame, CLVContainerView** ContainerView, + const char* Name = NULL, uint32 ResizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, + list_view_type Type = B_SINGLE_SELECTION_LIST, + bool hierarchical = false, bool horizontal = true, bool vertical = true, + bool scroll_view_corner = true, border_style border = B_NO_BORDER, + const BFont* LabelFont = be_plain_font) : + ColumnListView(Frame, ContainerView, Name, ResizingMode, flags, Type, hierarchical, + horizontal, vertical, scroll_view_corner, border, LabelFont) + { + container = *ContainerView; + } + + virtual ~SmartColumnListView() + { + } + + void MouseDown(BPoint point) + { + ColumnListView::MouseDown(point); + if (CurrentSelection() < 0) + container->Window()->PostMessage(MSG_LIST_DESELECT); + } + + private: + CLVContainerView *container; +}; + +// ----- MountItem ---------------------------------------------------------------------- + +class MountItem : public CLVEasyItem +{ + public: + MountItem(const char *text0, const char *text1, const char *text2) : + CLVEasyItem(0, false, false, 20.0) + { + // Here we're going to get the mini icon from a specific mime type + BRect bmpRect(0.0, 0.0, 15.0, 15.0); + BBitmap *icon = new BBitmap(bmpRect, B_CMAP8); + + BMimeType mime("application/x-vnd.BeServed-fileshare"); + mime.GetIcon(icon, B_MINI_ICON); + + SetColumnContent(0, icon, 2.0); + SetColumnContent(1, text0); + SetColumnContent(2, text1); + SetColumnContent(3, text2); + } + + ~MountItem() + { + } +}; + +// ----- HostInfoPanel ----------------------------------------------------------------- + +class HostInfoPanel : public BWindow +{ + public: + HostInfoPanel(BRect frame, const char *name, uint32 ipAddr) : + BWindow(frame, name, B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) + { + BRect r = Bounds(); + + strcpy(host, name); + address = ipAddr; + AddChild(new HostInfoView(r, name, address)); + + Show(); + } + + private: + char host[B_FILE_NAME_LENGTH + 1]; + uint32 address; +}; + + +class FileShareWindow : public BWindow +{ + public: + FileShareWindow(BWindow *win, BRect frame, const char *name, uint32 ipAddr) : + BWindow(frame, name, B_TITLED_WINDOW, B_NOT_ZOOMABLE) + { + parent = win; + strcpy(host, name); + address = ipAddr; + + CLVContainerView *containerView; + BRect r = Bounds(); + + MyColumnListView = new SmartColumnListView(r, &containerView, NULL, B_FOLLOW_TOP_BOTTOM | B_FOLLOW_LEFT_RIGHT, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST, + false, false, false, false, B_NO_BORDER); + + MyColumnListView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT)); + MyColumnListView->AddColumn(new CLVColumn("Resource", 140.0, CLV_SORT_KEYABLE, 50.0)); + MyColumnListView->AddColumn(new CLVColumn("Type", 90.0, CLV_SORT_KEYABLE)); + + MyColumnListView->SetSelectionMessage(new BMessage(MSG_SHARE_SELECT)); + MyColumnListView->SetInvocationMessage(new BMessage(MSG_SHARE_INVOKE)); + + AddCLVItems(MyColumnListView); + AddChild(containerView); + + SetSizeLimits(260, 2000, 110, 2000); + Show(); + } + + // AddCLVItems() + // + void AddCLVItems(ColumnListView* MyColumnListView) + { + extern int32 getShares(void *); + ThreadInfo *info = new ThreadInfo(); + info->SetColumnListView(MyColumnListView); + info->SetHostAddress(address); + thread_id shareThread = spawn_thread(getShares, "Get Shares", B_NORMAL_PRIORITY, info); + resume_thread(shareThread); + } + + void MessageReceived(BMessage *msg) + { + BListView *list; + int32 curItem; + + switch (msg->what) + { + case MSG_SHARE_SELECT: + break; + + case MSG_SHARE_INVOKE: + msg->FindPointer("source", (void **) &list); + curItem = list->CurrentSelection(); + if (curItem != -1) + { + CLVEasyItem *item = (CLVEasyItem *) MyColumnListView->ItemAt(curItem); + if (item) + { + const char *share = item->GetColumnContentText(1); + const char *type = item->GetColumnContentText(2); + + if (strcmp(type, "Shared Files") == 0) + mountToLocalFolder(host, (char *) share); + else + createSharedPrinter(host, (char *) share, 0); + } + } + break; + + default: + BWindow::MessageReceived(msg); + break; + } + } + + private: + // mountToLocalFolder() + // + void mountToLocalFolder(char *host, char *share) + { + char *folder = makeLocalFolder(host, share); + if (folder) + { + if (dev_for_path("/boot/home") == dev_for_path(folder)) + if (!mountFileShare(address, share, folder)) + return; + + updateMountList(host, share, folder); + showFolder(folder); + free(folder); + } + else + { + BAlert *alert = new BAlert("title", "An attempt to create a local mount point to access this shared volume has failed.", "OK"); + alert->Go(); + } + } + + // makeLocalFolder() + // + char *makeLocalFolder(char *host, char *share) + { + char *path = (char *) malloc(B_PATH_NAME_LENGTH); + if (!path) + return NULL; + + strcpy(path, "/boot/home/Connections"); + if (access(path, 0) != 0) + if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) + return NULL; + + strcat(path, "/"); + strcat(path, host); + if (access(path, 0) != 0) + if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) + return NULL; + + strcat(path, "/"); + strcat(path, share); + if (access(path, 0) != 0) + if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) + return NULL; + + return path; + } + + // getMountFolder() + // + void getMountFolder() + { + char path[B_PATH_NAME_LENGTH]; + entry_ref entryRef; + + find_directory(B_USER_DIRECTORY, 0, false, path, sizeof(path)); + BEntry entry(path, false); + entry.GetRef(&entryRef); + BFilePanel *filePanel = new BFilePanel(B_OPEN_PANEL, &be_app_messenger, &entryRef, B_DIRECTORY_NODE, false); + filePanel->Show(); + filePanel->Window()->SetTitle("Mount Location"); + filePanel->SetButtonLabel(B_DEFAULT_BUTTON, "Mount"); + } + + bool mountFileShare(uint32 address, char *share, const char *path) + { + blf_ctx ctx; + mount_bt_params params; + char hostname[256], msg[512], *folder; + int length; + port_id port; + + folder = strrchr(path, '/'); + if (folder) + folder++; + else + folder = (char *) path; + + unsigned int serverIP = ntohl(address); + +#ifndef BONE_VERSION + if (!be_roster->IsRunning(KSOCKETD_SIGNATURE)) + if (be_roster->Launch(KSOCKETD_SIGNATURE) < B_NO_ERROR) + { + printf("Network communications could not be started. The shared volume cannot be mounted.\n"); + BAlert *alert = new BAlert("", msg, "OK"); + alert->Go(); + return false; + } + + for (int32 i = 0; i < 10; i++) + { + port = find_port(KSOCKET_DAEMON_NAME); + + if (port < B_NO_ERROR) + snooze(1000000LL); + else + break; + } + + if (port < B_NO_ERROR) + { + sprintf(msg, "Network communications are not responding. The shared volume cannot be mounted.\n"); + BAlert *alert = new BAlert("", msg, "OK"); + alert->Go(); + return false; + } +#endif + + // Handle user authentication +// strcpy(user, crypt(user, "u0")); +// strcpy(password, crypt(password, "p1")); + if (getAuthentication(serverIP, share)) + { + BRect frame = Frame(); + frame.top += 75; + frame.left += 75; + frame.bottom = frame.top + 140; + frame.right = frame.left + 250; + LoginPanel *login = new LoginPanel(frame); + status_t loginExit; + wait_for_thread(login->Thread(), &loginExit); + if (login->IsCancelled()) + return false; + + // Copy the user name. + strcpy(params.user, login->user); + + // Copy the user name and password supplied in the authentication dialog. + sprintf(params.password, "%-*s%-*s", B_FILE_NAME_LENGTH, share, MAX_USERNAME_LENGTH, login->user); //crypt(password, "p1")); + length = strlen(params.password); + assert(length == BT_AUTH_TOKEN_LENGTH); + + params.password[length] = 0; + blf_key(&ctx, (unsigned char *) login->md5passwd, strlen(login->md5passwd)); + blf_enc(&ctx, (unsigned long *) params.password, length / 4); + } + else + params.user[0] = params.password[0] = 0; + + params.serverIP = serverIP; + params.server = host; + params._export = share; + params.folder = folder; + params.uid = 0; + params.gid = 0; + + gethostname(hostname, 256); + params.hostname = hostname; + + int result = mount("beserved_client", path, NULL, 0, ¶ms, sizeof(params)); + + if (result < B_NO_ERROR) + { + sprintf(msg, "The shared volume could not be mounted (%s).\n", strerror(errno)); + BAlert *alert = new BAlert("", msg, "OK"); + alert->Go(); + return false; + } + + return true; + } + + bool getAuthentication(unsigned int serverIP, char *shareName) + { + bt_inPacket *inPacket; + bt_outPacket *outPacket; + int security; + + security = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_PREMOUNT, 1, strlen(shareName)); + btRPCPutArg(outPacket, B_STRING_TYPE, shareName, strlen(shareName)); + inPacket = btRPCSimpleCall(serverIP, BT_TCPIP_PORT, outPacket); + if (inPacket) + { + security = btRPCGetInt32(inPacket); + free(inPacket->buffer); + free(inPacket); + } + + free(outPacket->buffer); + free(outPacket); + + return (security == BT_AUTH_BESURE); + } + + void updateMountList(char *host, char *share, char *path) + { + BMessage *relay; + relay = new BMessage(MSG_NEW_MOUNT); + relay->AddString("host", host); + relay->AddString("share", share); + relay->AddString("path", path); + + parent->PostMessage(relay); + } + + void showFolder(char *path) + { + char command[512]; + sprintf(command, "/boot/beos/system/Tracker \"%s\"", path); + system(command); + } + + bool isSharedPrinterInstalled(char *host, char *printer) + { + char path[B_PATH_NAME_LENGTH]; + + // If a printer by this name already exists, remove the existing configuration + // in favor of changes being applied. If not, just create the printer and move + // on. + find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/printers/"); + strcat(path, printer); + return (access(path, 0) == 0); + } + + void createSharedPrinter(char *host, char *printer, int type) + { + blf_ctx ctx; + hostent *ent; + char msg[512], user[MAX_USERNAME_LENGTH + 1], password[BT_AUTH_TOKEN_LENGTH * 2 + 1]; + int length; + + // Abort if the printer type is not valid. + if (type < 0 || type > 0) + return; + + BRect frame = Frame(); + frame.top += 75; + frame.left += 75; + frame.bottom = frame.top + 135; + frame.right = frame.left + 350; + InstallPrinterPanel *prtPanel = new InstallPrinterPanel(frame, host, printer); + status_t loginExit; + wait_for_thread(prtPanel->Thread(), &loginExit); + if (prtPanel->IsCancelled()) + return; + + // Get the IP address of the server. + ent = gethostbyname(host); + if (ent == NULL) + { + sprintf(msg, "The server %s, which hosts printer %s, cannot be found on the network.", host, printer); + BAlert *alert = new BAlert("", msg, "OK"); + alert->Go(); + return; + } + + unsigned int serverIP = ntohl(*((unsigned int *) ent->h_addr)); + + if (getAuthentication(serverIP, printer)) + { + BRect frame = Frame(); + frame.top += 75; + frame.left += 75; + frame.bottom = frame.top + 140; + frame.right = frame.left + 250; + LoginPanel *login = new LoginPanel(frame); + status_t loginExit; + wait_for_thread(login->Thread(), &loginExit); + if (login->IsCancelled()) + return; + + // Copy the user name. + strcpy(user, login->user); + + // Copy the user name and password supplied in the authentication dialog. + sprintf(password, "%-*s%-*s", B_FILE_NAME_LENGTH, printer, MAX_USERNAME_LENGTH, login->user); + length = strlen(password); + assert(length == BT_AUTH_TOKEN_LENGTH); + + password[length] = 0; + blf_key(&ctx, (unsigned char *) login->md5passwd, strlen(login->md5passwd)); + blf_enc(&ctx, (unsigned long *) password, length / 4); + } + else + user[0] = password[0] = 0; + + prtPanel->CreatePrinter(printer, host, type, user, password); + if (prtPanel->isDefault()) + prtPanel->SetDefaultPrinter(printer); + if (prtPanel->printTestPage()) + prtPanel->TestPrinter(printer); + } + + BWindow *parent; + SmartColumnListView *MyColumnListView; + char host[B_FILE_NAME_LENGTH]; + uint32 address; +}; + +// ----- InetHostView ----------------------------------------------------- + +class InetHostView : public BView +{ + public: + InetHostView(BRect rect) : + BView(rect, "InetHostView", B_FOLLOW_ALL, B_WILL_DRAW) + { + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.BeServed-inetserver"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r(10, 52, 310, 72); + editName = new BTextControl(r, "ShareName", "Name or Address:", "", NULL); + editName->SetDivider(90); + AddChild(editName); + + r.Set(155, 97, 225, 117); + BButton *okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_HOST_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(235, 97, 310, 117); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_HOST_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); + + editName->MakeFocus(); + } + + ~InetHostView() + { + } + + void Draw(BRect rect) + { + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + DrawString("Connect to Internet Host"); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("Specify the name or address of a computer located"); + MovePenTo(55, 40); + DrawString("outside your network, such as on the Internet."); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); + } + + BTextControl *editName; + + private: + BBitmap *icon; +}; + + +// ----- InetHostPanel ---------------------------------------------------------------------- + +class InetHostPanel : public BWindow +{ + public: + InetHostPanel(BRect frame, BWindow *win) : + BWindow(frame, "Internet Host", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) + { + parent = win; + + BRect r = Bounds(); + hostView = new InetHostView(r); + AddChild(hostView); + + Show(); + } + + // MessageReceived() + // + void MessageReceived(BMessage *msg) + { + BMessage *relay; + + switch (msg->what) + { + case MSG_HOST_OK: + relay = new BMessage(MSG_HOST_OK); + relay->AddString("host", hostView->editName->Text()); + parent->PostMessage(relay); + + case MSG_HOST_CANCEL: + BWindow::Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } + } + + private: + BWindow *parent; + InetHostView *hostView; +}; + +// ----- MyNetWindow -------------------------------------------------------------------------- + +class MyNetWindow : public BWindow +{ + public: + MyNetWindow(BRect frame) : + BWindow(frame, "My Network", B_TITLED_WINDOW, B_NOT_ZOOMABLE) + { + BRect r; + + r = Bounds(); + r.bottom = 85; + headerView = new MyNetHeaderView(r); + AddChild(headerView); + + CLVContainerView *containerView; + r = Bounds(); + r.top = r.bottom - 140; + r.bottom -= 40; + + MyColumnListView = new SmartColumnListView(r, &containerView, NULL, B_FOLLOW_BOTTOM | B_FOLLOW_LEFT_RIGHT, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST, + false, false, false, false, B_NO_BORDER); + + MyColumnListView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE | + CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT)); + MyColumnListView->AddColumn(new CLVColumn("Computer", 120.0, CLV_SORT_KEYABLE, 50.0)); + MyColumnListView->AddColumn(new CLVColumn("Share Name", 85.0, CLV_SORT_KEYABLE)); + MyColumnListView->AddColumn(new CLVColumn("Mounted At", 250.0, CLV_SORT_KEYABLE)); + + MyColumnListView->SetSelectionMessage(new BMessage(MSG_SHARE_SELECT)); + MyColumnListView->SetInvocationMessage(new BMessage(MSG_SHARE_OPEN)); + + AddCLVItems(MyColumnListView); + AddChild(containerView); + + r = Bounds(); + r.top = 85; + r.bottom -= 140; + netView = new MyNetView(r); + AddChild(netView); + + r = Bounds(); + r.top = r.bottom - 40; + shareView = new MyShareOptionView(r); + AddChild(shareView); + + SetSizeLimits(400, 2000, 270, 2000); + + Show(); + } + + // AddCLVItems() + // + void AddCLVItems(ColumnListView* MyColumnListView) + { + DIR *hosts, *shares; + struct dirent *hostInfo, *shareInfo; + struct stat st; + struct tm *mountTime; + char path[B_PATH_NAME_LENGTH]; + + hosts = opendir(BT_HOST_PATH); + if (hosts) + { + while ((hostInfo = readdir(hosts)) != NULL) + if (IsValid(hostInfo->d_name)) + { + sprintf(path, "%s/%s", BT_HOST_PATH, hostInfo->d_name); + shares = opendir(path); + if (shares) + { + while ((shareInfo = readdir(shares)) != NULL) + if (IsValid(shareInfo->d_name)) + { + sprintf(path, "%s/%s/%s", BT_HOST_PATH, hostInfo->d_name, shareInfo->d_name); + if (dev_for_path("/boot/home") != dev_for_path(path)) + { +// stat(path, &st); +// mountTime = localtime(&st.st_ctime); +// strftime(path, sizeof(path), "%a, %b %d %Y at %I:%M %p", mountTime); + MyColumnListView->AddItem(new MountItem(hostInfo->d_name, shareInfo->d_name, path)); + } + else + rmdir(path); + } + + closedir(shares); + } + } + + closedir(hosts); + } + } + + void MessageReceived(BMessage *msg) + { + BRect frame; + int32 curItem; + status_t exitStatus; + + switch (msg->what) + { + case MSG_HOST_INFO: + curItem = netView->list->CurrentSelection(); + if (curItem != -1) + { + IconListItem *item = (IconListItem *) netView->list->ItemAt(curItem); + if (item) + { + frame = Frame(); + frame.left += 100; + frame.top += 100; + frame.right = frame.left + 260; + frame.bottom = frame.top + 310; + HostInfoPanel *panel = new HostInfoPanel(frame, item->GetItemText(), item->GetItemData()); + } + } + break; + + case MSG_HOST_SELECT: + headerView->openBtn->SetEnabled(true); + headerView->hostBtn->SetEnabled(true); + break; + + case MSG_LIST_DESELECT: + if (MyColumnListView->CountItems() > 0 && MyColumnListView->CurrentSelection() == -1) + { + shareView->openBtn->SetEnabled(false); + shareView->unmountBtn->SetEnabled(false); + } + else + { + headerView->openBtn->SetEnabled(false); + headerView->hostBtn->SetEnabled(false); + } + break; + + case MSG_SHARE_SELECT: + shareView->openBtn->SetEnabled(true); + shareView->unmountBtn->SetEnabled(true); + break; + + case MSG_HOST_INVOKE: + curItem = netView->list->CurrentSelection(); + if (curItem != -1) + { + IconListItem *item = (IconListItem *) netView->list->ItemAt(curItem); + if (item) + { + frame = Frame(); + frame.left += 100; + frame.top += 100; + frame.right = frame.left + 260; + frame.bottom = frame.top + 300; + FileShareWindow *win = new FileShareWindow(this, frame, item->GetItemText(), item->GetItemData()); + } + } + break; + + case MSG_HOST_REFRESH: + netView->Refresh(); + break; + + case MSG_INET_HOSTS: + { + frame = Frame(); + frame.left += 150; + frame.top += 50; + frame.right = frame.left + 320; + frame.bottom = frame.top + 128; + InetHostPanel *win = new InetHostPanel(frame, this); + wait_for_thread(win->Thread(), &exitStatus); + } + break; + + case MSG_HOST_OK: + { + const char *name; + msg->FindString("host", &name); + + hostent *ent = gethostbyname(name); + if (ent) + { + char buffer[256]; + frame = Frame(); + frame.left += 100; + frame.top += 100; + frame.right = frame.left + 260; + frame.bottom = frame.top + 300; + sprintf(buffer, "%d.%d.%d.%d", (uint8) ent->h_addr_list[0][0], + (uint8) ent->h_addr_list[0][1], (uint8) ent->h_addr_list[0][2], + (uint8) ent->h_addr_list[0][3]); + FileShareWindow *win = new FileShareWindow(this, frame, name, (uint32) inet_addr(buffer)); + } + else + { + BAlert *alert = new BAlert("Error", "The specified name or address cannot be contacted.", "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); + alert->Go(); + } + } + break; + + case MSG_NEW_MOUNT: + { + const char *host, *share, *path; + msg->FindString("host", &host); + msg->FindString("share", &share); + msg->FindString("path", &path); + MyColumnListView->LockLooper(); + MyColumnListView->AddItem(new MountItem(host, share, path)); + MyColumnListView->UnlockLooper(); + } + break; + + case MSG_SHARE_OPEN: + curItem = MyColumnListView->CurrentSelection(); + if (curItem != -1) + { + char command[512]; + MountItem *item = (MountItem *) MyColumnListView->ItemAt(curItem); + const char *path = item->GetColumnContentText(3); + sprintf(command, "/boot/beos/system/Tracker \"%s\"", path); + system(command); + } + break; + + case MSG_SHARE_UNMOUNT: + curItem = MyColumnListView->CurrentSelection(); + if (curItem != -1) + { + MountItem *item = (MountItem *) MyColumnListView->ItemAt(curItem); + const char *path = item->GetColumnContentText(3); + int error = unmount(path); + if (error == 0) + { + MyColumnListView->LockLooper(); + MyColumnListView->RemoveItems(curItem, 1); + MyColumnListView->UnlockLooper(); + + shareView->openBtn->SetEnabled(false); + shareView->unmountBtn->SetEnabled(false); + } + } + break; + + default: + BWindow::MessageReceived(msg); + break; + } + } + + bool QuitRequested() + { + be_app->PostMessage(B_QUIT_REQUESTED); + return true; + } + + private: + BMenuBar *menuBar; + MyNetHeaderView *headerView; + MyNetView *netView; + MyShareOptionView *shareView; + ColumnListView *MyColumnListView; +}; + + +class MyNetApp : public BApplication +{ + public: + MyNetApp() : BApplication("application/x-vnd.Teldar-MyNetwork") + { + checkMimeTypes(); + BRect frame(100, 150, 500, 600); + MyNetWindow *win = new MyNetWindow(frame); + } + + void RefsReceived(BMessage *msg) + { + entry_ref entryRef; + BPath path; + BEntry entry; + + switch (msg->what) + { + case B_REFS_RECEIVED: + msg->FindRef("refs", &entryRef); + entry.SetTo(&entryRef, true); + entry.GetPath(&path); +// mountFileShare(lastHost, lastShare, path.Path()); + break; + + default: + BApplication::RefsReceived(msg); + break; + } + } + + private: + void buildMimeDB() + { + BMimeType mime; + BMessage msg; + char *data; + ssize_t bytes; + FILE *fp = fopen("/boot/home/mime.txt", "w"); + mime.GetInstalledTypes(&msg); + for (int i = 0; msg.FindString("types", i, (const char **) &data) == B_OK; i++) + { + BMimeType t(data); + BMessage m; + char *ext; + if (t.GetFileExtensions(&m) == B_OK) + { + for (int j = 0; m.FindString("extensions", j, (const char **) &ext) == B_OK; j++) + fprintf(fp, "%-6s%s\n", ext, data); + } + } + fclose(fp); + } + + void checkMimeTypes() + { + BMimeType mime; + mime.SetTo("application/x-vnd.BeServed-fileserver"); + mime.Delete(); + if (!mime.IsInstalled()) + { + mime.Install(); + mime.SetShortDescription("Network File Server"); + mime.SetLongDescription("A network server running BeServed"); + setMimeIcon(&mime, MYNET_ICON_HOST_LARGE, B_LARGE_ICON); + setMimeIcon(&mime, MYNET_ICON_HOST_SMALL, B_MINI_ICON); + } + + mime.SetTo("application/x-vnd.BeServed-inetserver"); + mime.Delete(); + if (!mime.IsInstalled()) + { + mime.Install(); + mime.SetShortDescription("Public File Server"); + mime.SetLongDescription("A remote network server running BeServed"); + setMimeIcon(&mime, MYNET_ICON_INETHOST_LARGE, B_LARGE_ICON); + setMimeIcon(&mime, MYNET_ICON_INETHOST_SMALL, B_MINI_ICON); + } + + mime.SetTo("application/x-vnd.BeServed-fileshare"); + mime.Delete(); + if (!mime.IsInstalled()) + { + mime.Install(); + mime.SetShortDescription("Shared Volume"); + mime.SetLongDescription("A BeServed network shared volume"); + setMimeIcon(&mime, MYNET_ICON_SHARE_LARGE, B_LARGE_ICON); + setMimeIcon(&mime, MYNET_ICON_SHARE_SMALL, B_MINI_ICON); + } + } + + bool setMimeIcon(BMimeType *mime, int32 resourceID, icon_size which) + { + BMessage archive; + size_t size; + char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), resourceID, &size); + if (bits) + if (archive.Unflatten(bits) == B_OK) + { + BBitmap *icon = new BBitmap(&archive); + mime->SetIcon(icon, which); + return true; + } + + return false; + } +}; + + +int main() +{ + MyNetApp *app = new MyNetApp(); + app->Run(); + + return 0; +} + +/* + r = Bounds(); + r.bottom = 18.0; + menuBar = new BMenuBar(r, "menu_bar"); + BMenu *compMenu = new BMenu("Computer"); + compMenu->AddItem(new BMenuItem("Open", new BMessage(MENU_MSG_COPEN), 'O', B_COMMAND_KEY)); + compMenu->AddItem(new BMenuItem("Find...", new BMessage(MENU_MSG_CFIND), 'F', B_COMMAND_KEY)); + compMenu->AddItem(new BMenuItem("Quit", new BMessage(MENU_MSG_QUIT), 'Q', B_COMMAND_KEY)); + menuBar->AddItem(compMenu); + + AddChild(menuBar); +*/ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetView.cpp b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetView.cpp new file mode 100644 index 0000000000..75e0394609 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetView.cpp @@ -0,0 +1,667 @@ +#include "Mime.h" +#include "TypeConstants.h" +#include "Application.h" +#include "InterfaceDefs.h" +#include "TranslationUtils.h" +#include "Alert.h" +#include "Button.h" +#include "ListView.h" +#include "StatusBar.h" +#include "Errors.h" +#include "OS.h" + +// ColumnListView includes +#include "ColumnListView.h" +#include "CLVColumn.h" +#include "CLVEasyItem.h" +#include "NewStrings.h" + +// POSIX includes +#include "errno.h" +#include "malloc.h" +#include "socket.h" +#include "signal.h" +#include "netdb.h" + +#include "betalk.h" +#include "sysdepdefs.h" +#include "MyNetView.h" + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define TEXT_WARN_NETUNREACH "A network error has prevented the discovery of other computers on your network. Consequently, the list of those computers cannot be displayed." + +int32 getHosts(void *data); +int32 getShares(void *data); +int32 getHostInfo(void *data); +void recvAlarm(int signal); +void networkError(int error); + + +// ----- ThreadInfo -------------------------------------------------------------------- + +ThreadInfo::ThreadInfo() +{ + address = 0; + listView = NULL; +} + +ThreadInfo::~ThreadInfo() +{ +} + +// ----- MyNetHeaderView --------------------------------------------------------------- + +MyNetHeaderView::MyNetHeaderView(BRect rect) + : BView(rect, "MyNetHeaderView", B_FOLLOW_TOP | B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW) +{ + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.Teldar-MyNetwork"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r; + r.Set(15, 55, 70, 75); + openBtn = new BButton(r, "OpenBtn", "Open", new BMessage(MSG_HOST_INVOKE)); + openBtn->SetEnabled(false); + AddChild(openBtn); + + r.Set(77, 55, 215, 75); + hostBtn = new BButton(r, "HostBtn", "About this Computer...", new BMessage(MSG_HOST_INFO)); + hostBtn->SetEnabled(false); + AddChild(hostBtn); + + r.Set(222, 55, 288, 75); + AddChild(new BButton(r, "RefreshBtn", "Refresh", new BMessage(MSG_HOST_REFRESH))); + + r.Set(295, 55, 390, 75); + AddChild(new BButton(r, "InternetBtn", "Internet Host...", new BMessage(MSG_INET_HOSTS))); +} + +MyNetHeaderView::~MyNetHeaderView() +{ +} + +void MyNetHeaderView::Draw(BRect rect) +{ + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + DrawString("My Network Browser"); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("This utility allows you to connect to remote computers and access"); + MovePenTo(55, 40); + DrawString("resources, such as files and printers, that others have chosen to share."); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); +} + +// ----- MyShareOptionView --------------------------------------------------------------- + +MyShareOptionView::MyShareOptionView(BRect rect) + : BView(rect, "MyNetHeaderView", B_FOLLOW_BOTTOM | B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW) +{ + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect r; + r.Set(15, 5, 70, 25); + openBtn = new BButton(r, "OpenBtn", "Open", new BMessage(MSG_SHARE_OPEN)); + openBtn->SetEnabled(false); + AddChild(openBtn); + + r.Set(77, 5, 160, 25); + unmountBtn = new BButton(r, "UnmountBtn", "Disconnect", new BMessage(MSG_SHARE_UNMOUNT)); + unmountBtn->SetEnabled(false); + AddChild(unmountBtn); +} + +MyShareOptionView::~MyShareOptionView() +{ +} + +void MyShareOptionView::Draw(BRect rect) +{ + BRect r = Bounds(); + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); +} + +// ----- MyNetView --------------------------------------------------------------- + +MyNetView::MyNetView(BRect rect) + : BView(rect, "MyNetView", B_FOLLOW_TOP_BOTTOM | B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW) +{ + list = new IconListView(Bounds(), "Other Computers"); + list->SetSelectionMessage(new BMessage(MSG_HOST_SELECT)); + list->SetInvocationMessage(new BMessage(MSG_HOST_INVOKE)); + + // Here we're going to get the mini icon from a specific mime type + BRect bmpRect(0.0, 0.0, 15.0, 15.0); + fileIcon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.BeServed-fileserver"); + mime.GetIcon(fileIcon, B_MINI_ICON); + + thread_id hostThread = spawn_thread(getHosts, "Get Hosts", B_NORMAL_PRIORITY, this); + resume_thread(hostThread); + + AddChild(new BScrollView("scroll", list, B_FOLLOW_ALL, 0, false, true)); +} + +MyNetView::~MyNetView() +{ + void *item; + int32 i; + + for (i = 0; item = list->ItemAt(i); i++) + delete item; + + delete list; + delete fileIcon; +} + +void MyNetView::AddHost(char *hostName, uint32 address) +{ + char buffer[256]; + + strcpy(buffer, hostName); + IconListItem *item = new IconListItem(fileIcon, buffer, address, 0, false); + + list->LockLooper(); + list->AddItem(item); + list->UnlockLooper(); +} + +void MyNetView::Refresh() +{ + list->LockLooper(); + list->RemoveItems(0, list->CountItems()); + list->UnlockLooper(); + + thread_id hostThread = spawn_thread(getHosts, "Get Hosts", B_NORMAL_PRIORITY, this); + resume_thread(hostThread); +} + +// ----- ResourceItem ------------------------------------------------------------------ + +class ResourceItem : public CLVEasyItem +{ + public: + ResourceItem::ResourceItem(const char *text0, int type) + : CLVEasyItem(0, false, false, 20.0) + { + // Here we're going to get the mini icon from a specific mime type + BRect bmpRect(0.0, 0.0, 15.0, 15.0); + BBitmap *icon = new BBitmap(bmpRect, B_CMAP8); + + BMimeType mime(type == BT_SHARED_FOLDER ? "application/x-vnd.BeServed-fileshare" + : "application/x-vnd.Be.printer"); + mime.GetIcon(icon, B_MINI_ICON); + + SetColumnContent(0, icon, 2.0); + SetColumnContent(1, text0); + SetColumnContent(2, type == BT_SHARED_FOLDER ? "Shared Files" : "Shared Printer"); + } + + ResourceItem::~ResourceItem() + { + } +}; + +// ----- FileShareView ----------------------------------------------------- + +FileShareView::FileShareView(BRect rect, const char *name, uint32 ipAddr) + : BView(rect, "FileShareView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + strcpy(host, name); + address = ipAddr; + + list = new IconListView(Bounds(), "File Shares"); + list->SetSelectionMessage(new BMessage(MSG_SHARE_SELECT)); + list->SetInvocationMessage(new BMessage(MSG_SHARE_INVOKE)); + + // Here we're going to get the mini icon from a specific mime type + BRect bmpRect(0.0, 0.0, 15.0, 15.0); + fileIcon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.BeServed-fileshare"); + mime.GetIcon(fileIcon, B_MINI_ICON); + printerIcon = new BBitmap(bmpRect, B_CMAP8); + mime.SetTo("application/x-vnd.Be.printer"); + mime.GetIcon(printerIcon, B_MINI_ICON); + + thread_id shareThread = spawn_thread(getShares, "Get Shares", B_NORMAL_PRIORITY, this); + resume_thread(shareThread); + + AddChild(new BScrollView("scroll", list, B_FOLLOW_ALL, 0, false, true)); +} + +FileShareView::~FileShareView() +{ + void *item; + int32 i; + + for (i = 0; item = list->ItemAt(i); i++) + delete item; + + delete list; + delete printerIcon; + delete fileIcon; +} + +void FileShareView::AddShare(char *shareName) +{ + char buffer[256]; + + strcpy(buffer, shareName); + IconListItem *item = new IconListItem(fileIcon, buffer, 0, 0, false); + + list->LockLooper(); + list->AddItem(item); + list->UnlockLooper(); +} + +void FileShareView::AddPrinter(char *printerName) +{ + char buffer[256]; + + strcpy(buffer, printerName); + IconListItem *item = new IconListItem(printerIcon, buffer, 0, 0, false); + + list->LockLooper(); + list->AddItem(item); + list->UnlockLooper(); +} + +// ----- HostInfoView ----------------------------------------------------- + +HostInfoView::HostInfoView(BRect rect, const char *name, uint32 ipAddr) + : BView(rect, "HostInfoView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + address = ipAddr; + + hostInfo.cpus = 0; + thread_id infoThread = spawn_thread(getHostInfo, "Get Host Info", B_NORMAL_PRIORITY, this); + resume_thread(infoThread); + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + + BMimeType mime("application/x-vnd.BeServed-fileserver"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r(40, 55, 230, 120); + BListView *aliasList = new BListView(r, "Aliases", B_SINGLE_SELECTION_LIST); + AddChild(new BScrollView("ScrollAliases", aliasList, B_FOLLOW_LEFT | B_FOLLOW_TOP, + 0, false, true)); + + r.top = 145; + r.bottom = 210; + BListView *addressList = new BListView(r, "Addresses", B_SINGLE_SELECTION_LIST); + AddChild(new BScrollView("ScrollAddresses", addressList, B_FOLLOW_LEFT | B_FOLLOW_TOP, + 0, false, true)); + + r.top = 275; + r.bottom = 305; + r.left = 38; + r.right = 245; + status = new BStatusBar(r, "Connections"); + status->SetBarHeight(13.0); + AddChild(status); + + ent = gethostbyaddr((char *) &ipAddr, sizeof(ipAddr), AF_INET); + if (ent) + { + char buf[50]; + int i; + for (i = 0; ent->h_aliases[i] != 0; i++) + aliasList->AddItem(new BStringItem(ent->h_aliases[i])); + + for (i = 0; ent->h_addr_list[i] != 0; i++) + { + sprintf(buf, "%d.%d.%d.%d", (uint8) ent->h_addr_list[i][0], (uint8) ent->h_addr_list[i][1], + (uint8) ent->h_addr_list[i][2], (uint8) ent->h_addr_list[i][3]); + addressList->AddItem(new BStringItem(buf)); + } + } +} + +HostInfoView::~HostInfoView() +{ +} + +void HostInfoView::Draw(BRect rect) +{ + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color green = { 0, 255, 0, 255 }; + rgb_color red = { 255, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color shadow = { 190, 190, 190, 255 }; + char buf[50]; + + SetViewColor(gray); + SetLowColor(shadow); + r.right = 35; + FillRect(r, B_SOLID_LOW); + r = Bounds(); + r.left = 35; + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + if (ent) + { + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(14); + MovePenTo(50, 25); + DrawString(ent->h_name); + } + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(40, 50); + DrawString("Aliases:"); + + MovePenTo(40, 140); + DrawString("Known Addresses:"); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(40, 230); + DrawString("System:"); + MovePenTo(100, 230); + if (hostInfo.cpus > 0) + DrawString(hostInfo.system); + + MovePenTo(40,243); + DrawString("Network:"); + MovePenTo(100, 243); + if (hostInfo.cpus > 0) + DrawString(hostInfo.beServed); + + MovePenTo(40, 256); + DrawString("Platform:"); + MovePenTo(100, 256); + if (hostInfo.cpus > 0) + DrawString(hostInfo.platform); + + MovePenTo(40, 269); + DrawString("Processors:"); + MovePenTo(100, 269); + if (hostInfo.cpus > 0) + { + sprintf(buf, "%ld", hostInfo.cpus); + DrawString(buf); + } + + if (hostInfo.cpus > 0) + { + double pct = hostInfo.connections * 100.0 / hostInfo.maxConnections; + sprintf(buf, "%ld of %ld total", hostInfo.connections, hostInfo.maxConnections); + status->SetMaxValue(hostInfo.maxConnections); + status->Reset(); + status->Update(hostInfo.connections, "Connections", buf); + status->SetBarColor(pct < 90.0 ? green : red); + } + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); +} + +// ----- Thread Code ----------------------------------------------------- + +int32 getHosts(void *data) +{ + bt_request request; + struct sockaddr_in ourAddr, toAddr, fromAddr; + int sock, addrLen, bytes; + char buffer[256]; +#ifdef SO_BROADCAST + int on = 1; +#endif + + MyNetView *view = (MyNetView *) data; + + memset(&toAddr, 0, sizeof(toAddr)); + toAddr.sin_family = AF_INET; + toAddr.sin_port = htons(BT_QUERYHOST_PORT); + toAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); + + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock == INVALID_SOCKET) + return 0; + + memset(&ourAddr, 0, sizeof(ourAddr)); + ourAddr.sin_family = AF_INET; + ourAddr.sin_port = htons(BT_QUERYHOST_PORT); + ourAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(sock, (struct sockaddr *) &ourAddr, sizeof(ourAddr))) + if (errno != EADDRINUSE) + { + closesocket(sock); + return 0; + } + + // Normally, a setsockopt() call is necessary to turn broadcast mode on + // explicitly, although some versions of Unix don't care. BeOS doesn't + // currently even define SO_BROADCAST, unless you have BONE installed. +#ifdef SO_BROADCAST + setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); +#endif + signal(SIGALRM, recvAlarm); + + strcpy(request.signature, BT_RPC_SIGNATURE); + request.command = BT_REQ_HOST_PROBE; + bytes = sendto(sock, (char *) &request, sizeof(request), 0, (struct sockaddr *) &toAddr, sizeof(toAddr)); + if (bytes == -1) + { + networkError(errno); + closesocket(sock); + return 0; + } + + alarm(5); + + while (1) + { + addrLen = sizeof(fromAddr); + bytes = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *) &fromAddr, &addrLen); + if (bytes < 0) + { + if (errno == EINTR) + break; + } + else if (bytes > 0) + if (strncmp(buffer, BT_RPC_SIGNATURE, strlen(BT_RPC_SIGNATURE)) != 0) + { + struct sockaddr_in *sin = (struct sockaddr_in *) &fromAddr; + hostent *ent = gethostbyaddr((char *) &sin->sin_addr, sizeof(sin->sin_addr), AF_INET); + if (ent) + view->AddHost(ent->h_name, *((uint32 *) &sin->sin_addr)); + else + { + uint8 *p = (uint8 *) &sin->sin_addr; + sprintf(buffer, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + view->AddHost(buffer, *((uint32 *) &sin->sin_addr)); + } + } + } + + alarm(0); + signal(SIGALRM, SIG_DFL); + closesocket(sock); + return 1; +} + +int32 getShares(void *data) +{ + bt_request request; + bt_resource resource; + struct sockaddr_in ourAddr, toAddr, fromAddr; + char buffer[8192]; + int sock, addrLen, bytes, bufPos = 0; + + ThreadInfo *info = (ThreadInfo *) data; + unsigned int serverIP = ntohl(info->GetHostAddress()); + + memset(&toAddr, 0, sizeof(toAddr)); + toAddr.sin_family = AF_INET; + toAddr.sin_port = htons(BT_QUERYHOST_PORT); + toAddr.sin_addr.s_addr = htonl(serverIP); + + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock == INVALID_SOCKET) + return 0; + + memset(&ourAddr, 0, sizeof(ourAddr)); + ourAddr.sin_family = AF_INET; + ourAddr.sin_port = htons(BT_QUERYHOST_PORT); + ourAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(sock, (struct sockaddr *) &ourAddr, sizeof(ourAddr))) + if (errno != EADDRINUSE) + { + closesocket(sock); + return 0; + } + + strcpy(request.signature, BT_RPC_SIGNATURE); + request.command = BT_REQ_SHARE_PROBE; + sendto(sock, (char *) &request, sizeof(request), 0, (struct sockaddr *) &toAddr, sizeof(toAddr)); + + signal(SIGALRM, recvAlarm); + alarm(4); + + addrLen = sizeof(fromAddr); + bytes = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *) &fromAddr, &addrLen); + if (bytes > 0) + if (strncmp(buffer, BT_RPC_SIGNATURE, strlen(BT_RPC_SIGNATURE)) != 0) + { + info->GetColumnListView()->LockLooper(); + + while (bufPos < bytes) + { + memcpy(&resource, buffer + bufPos, sizeof(bt_resource)); + resource.type = B_LENDIAN_TO_HOST_INT32(resource.type); + resource.subType = B_LENDIAN_TO_HOST_INT32(resource.subType); + if (resource.type == BT_SHARED_NULL) + break; + + bufPos += sizeof(bt_resource); + info->GetColumnListView()->AddItem(new ResourceItem(resource.name, resource.type)); + } + + info->GetColumnListView()->UnlockLooper(); + } + + alarm(0); + signal(SIGALRM, SIG_DFL); + closesocket(sock); + return 1; +} + +int32 getHostInfo(void *data) +{ + bt_request request; + struct sockaddr_in ourAddr, toAddr, fromAddr; + char buffer[1024]; + int sock, addrLen, bytes; + bool retry = true; + + HostInfoView *view = (HostInfoView *) data; + unsigned int serverIP = ntohl(view->address); + + memset(&toAddr, 0, sizeof(toAddr)); + toAddr.sin_family = AF_INET; + toAddr.sin_port = htons(BT_QUERYHOST_PORT); + toAddr.sin_addr.s_addr = htonl(serverIP); + + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock == INVALID_SOCKET) + return 0; + + memset(&ourAddr, 0, sizeof(ourAddr)); + ourAddr.sin_family = AF_INET; + ourAddr.sin_port = htons(BT_QUERYHOST_PORT); + ourAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(sock, (struct sockaddr *) &ourAddr, sizeof(ourAddr))) + if (errno != EADDRINUSE) + { + closesocket(sock); + return 0; + } + +sendReq: + strcpy(request.signature, BT_RPC_SIGNATURE); + request.command = BT_REQ_HOST_INFO; + sendto(sock, (char *) &request, sizeof(request), 0, (struct sockaddr *) &toAddr, sizeof(toAddr)); + + signal(SIGALRM, recvAlarm); + alarm(3); + + addrLen = sizeof(fromAddr); + bytes = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *) &fromAddr, &addrLen); + if (bytes > 0) + { + memcpy(&view->hostInfo, buffer, sizeof(bt_hostinfo)); + + view->hostInfo.cpus = B_LENDIAN_TO_HOST_INT32(view->hostInfo.cpus); + view->hostInfo.connections = B_LENDIAN_TO_HOST_INT32(view->hostInfo.connections); + view->hostInfo.maxConnections = B_LENDIAN_TO_HOST_INT32(view->hostInfo.maxConnections); + } + else if (retry) + { + retry = false; + goto sendReq; + } + + alarm(0); + signal(SIGALRM, SIG_DFL); + closesocket(sock); + return 1; +} + +void recvAlarm(int signal) +{ + return; +} + +void networkError(int error) +{ + char errMsg[512]; + sprintf(errMsg, "%s\n\nDetails: %s", TEXT_WARN_NETUNREACH, strerror(error)); + BAlert *alert = new BAlert("Error", errMsg, "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT); + alert->Go(); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetView.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetView.h new file mode 100644 index 0000000000..e2e5525a84 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetView.h @@ -0,0 +1,128 @@ +#ifndef _MYNETVIEW_H_ +#define _MYNETVIEW_H_ + +#include +#include +#include +#include +#include + +#include + +#include "IconListItem.h" + + +class MyNetView : public BView +{ + public: + MyNetView(BRect rect); + ~MyNetView(); + + void AddHost(char *hostName, uint32 address); + void Refresh(); + + IconListView *list; + + private: + BBitmap *fileIcon; + BMenuBar *menuBar; +}; + + +class FileShareView : public BView +{ + public: + FileShareView(BRect rect, const char *name, uint32 ipAddr); + ~FileShareView(); + + void AddShare(char *shareName); + void AddPrinter(char *printerName); + + IconListView *list; + char host[B_FILE_NAME_LENGTH]; + uint32 address; + + private: + BBitmap *fileIcon; + BBitmap *printerIcon; +}; + + +class HostInfoView : public BView +{ + public: + HostInfoView(BRect rect, const char *name, uint32 ipAddr); + ~HostInfoView(); + + void Draw(BRect rect); + + uint32 address; + bt_hostinfo hostInfo; + + private: + hostent *ent; + BBitmap *icon; + BStatusBar *status; +}; + + +class MyNetHeaderView : public BView +{ + public: + MyNetHeaderView(BRect rect); + ~MyNetHeaderView(); + + void Draw(BRect rect); + + BButton *openBtn; + BButton *hostBtn; + + private: + BBitmap *icon; +}; + + +class MyShareOptionView : public BView +{ + public: + MyShareOptionView(BRect rect); + ~MyShareOptionView(); + + void Draw(BRect rect); + + BButton *openBtn; + BButton *unmountBtn; +}; + + +class ThreadInfo +{ + public: + ThreadInfo(); + ~ThreadInfo(); + + ColumnListView *GetColumnListView() { return listView; } + uint32 GetHostAddress() { return address; } + + void SetColumnListView(ColumnListView *clv) { listView = clv; } + void SetHostAddress(uint32 ipAddr) { address = ipAddr; } + + private: + ColumnListView *listView; + uint32 address; +}; + +const int32 MSG_HOST_SELECT = 'HSel'; +const int32 MSG_HOST_INVOKE = 'HInv'; +const int32 MSG_SHARE_SELECT = 'SSel'; +const int32 MSG_SHARE_INVOKE = 'SInv'; +const int32 MSG_HOST_INFO = 'HInf'; +const int32 MSG_INET_HOSTS = 'HInt'; +const int32 MSG_HOST_OK = 'HOky'; +const int32 MSG_HOST_CANCEL = 'HCan'; +const int32 MSG_HOST_REFRESH = 'HRef'; +const int32 MSG_SHARE_OPEN = 'SOpn'; +const int32 MSG_SHARE_UNMOUNT = 'SUmt'; +const int32 MSG_NEW_MOUNT = 'NMnt'; + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetwork.proj b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetwork.proj new file mode 100644 index 0000000000..784f093917 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetwork.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetwork_BONE.proj b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetwork_BONE.proj new file mode 100644 index 0000000000..810fdf032f Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/MyNetwork_BONE.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/Resource.rsrc b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/Resource.rsrc new file mode 100644 index 0000000000..9b6a2517d2 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/Resource.rsrc differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/besure_auth.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/besure_auth.h new file mode 100644 index 0000000000..003ed4ec66 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/besure_auth.h @@ -0,0 +1,75 @@ +#ifndef _BESURE_AUTH_H_ +#define _BESURE_AUTH_H_ + +#include + +#define USER_FLAG_DISABLED 0x00000001 +#define USER_FLAG_INIT_EXPIRE 0x00000002 +#define USER_FLAG_DAYS_EXPIRE 0x00000004 +#define USER_FLAG_PW_LOCKED 0x00000008 + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +typedef void (*recordServerFunc)(char *name, uint32 addr); + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE bool createUser(char *user, char *password); +_IMPEXP_BESURE bool createGroup(char *group); +_IMPEXP_BESURE bool removeUser(char *user); +_IMPEXP_BESURE bool removeGroup(char *group); +_IMPEXP_BESURE bool addUserToGroup(char *user, char *group); +_IMPEXP_BESURE bool removeUserFromGroup(char *user, char *group); +_IMPEXP_BESURE bool isUserInGroup(char *user, char *group); + +_IMPEXP_BESURE bool setUserFullName(char *user, char *fullName); +_IMPEXP_BESURE bool setUserDesc(char *user, char *desc); +_IMPEXP_BESURE bool setUserPassword(char *user, char *password); +_IMPEXP_BESURE bool setUserFlags(char *user, uint32 flags); +_IMPEXP_BESURE bool setUserDaysToExpire(char *user, uint32 days); +_IMPEXP_BESURE bool setUserHome(char *user, char *home); +_IMPEXP_BESURE bool setUserGroup(char *user, char *group); +_IMPEXP_BESURE bool setGroupDesc(char *group, char *desc); + +_IMPEXP_BESURE bool getUserFullName(char *user, char *fullName, int bufSize); +_IMPEXP_BESURE bool getUserDesc(char *user, char *desc, int bufSize); +_IMPEXP_BESURE bool getUserPassword(char *user, char *password, int bufSize); +_IMPEXP_BESURE bool getUserFlags(char *user, uint32 *flags); +_IMPEXP_BESURE bool getUserDaysToExpire(char *user, uint32 *days); +_IMPEXP_BESURE bool getUserHome(char *user, char *home, int bufSize); +_IMPEXP_BESURE bool getUserGroup(char *user, char *group, int bufSize); +_IMPEXP_BESURE bool getGroupDesc(char *group, char *desc, int bufSize); + +_IMPEXP_BESURE bool isServerRecordingLogins(char *server); +_IMPEXP_BESURE bool setServerRecordingLogins(char *server, bool recording); + +_IMPEXP_BESURE void MakeServerKey(char *server, char *key); + +_IMPEXP_BESURE DIR *OpenUsers(); +_IMPEXP_BESURE dirent_t *ReadUser(DIR *dir); +_IMPEXP_BESURE void CloseUsers(DIR *dir); +_IMPEXP_BESURE DIR *OpenGroups(); +_IMPEXP_BESURE dirent_t *ReadGroup(DIR *dir); +_IMPEXP_BESURE void CloseGroups(DIR *dir); +_IMPEXP_BESURE DIR *OpenGroup(char *group); +_IMPEXP_BESURE dirent_t *ReadGroupMember(DIR *dir); +_IMPEXP_BESURE void CloseGroup(DIR *dir); +_IMPEXP_BESURE int GetServerList(recordServerFunc recServ); + +_IMPEXP_BESURE bool GetKeyValue(const char *fileName, const char *key, char *value, int bufSize); +_IMPEXP_BESURE bool GetKeyInt(const char *fileName, const char *key, int *value); +_IMPEXP_BESURE bool SetKeyValue(const char *fileName, const char *key, const char *value); +_IMPEXP_BESURE bool SetKeyInt(const char *fileName, const char *key, int value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/betalk.h new file mode 100644 index 0000000000..af38d0d926 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +// The different types of network resources supported by BeServed. +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRITNER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 32768 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 128 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int nsid; + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +typedef struct rpcInfo +{ + thread_id rpcThread; + int32 quitXID; + + uint32 serverIP; + int32 serverPort; + int s; +} bt_rpcinfo; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket inPacket; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/btAddOn.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/btAddOn.h new file mode 100644 index 0000000000..c3096a6f89 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/btAddOn.h @@ -0,0 +1,139 @@ +#ifndef _NFS_ADD_ON_H +#define _NFS_ADD_ON_H + +#include "fsproto.h" +#include "betalk.h" + +#include +#include +#include + +struct mount_bt_params +{ + unsigned int serverIP; + char *server; + char *_export; + uid_t uid; + gid_t gid; + char *hostname; + char *folder; + char user[MAX_USERNAME_LENGTH + 1]; + char password[BT_AUTH_TOKEN_LENGTH * 2 + 1]; +}; + +struct fs_node +{ + vnode_id vnid; + struct fs_node *next; +}; + +struct fs_nspace +{ + nspace_id nsid; + + thread_id tid; + bool quit; + int s; + + struct sockaddr_in mountAddr,nfsAddr; + + int32 xid; + + vnode_id rootid; + + sem_id sem; + struct fs_node *first; + + struct mount_bt_params params; +}; + +struct fs_file_cookie +{ + int omode; + off_t original_size; + struct stat st; +}; + +typedef struct fs_nspace fs_nspace; +typedef struct fs_node fs_node; +typedef struct fs_file_cookie fs_file_cookie; + +int fs_read_vnode(fs_nspace *ns, vnode_id vnid, char r, fs_node **node); +int fs_write_vnode(fs_nspace *ns, fs_node *node, char r); + +int fs_walk(fs_nspace *ns, fs_node *base, const char *file, char **newpath, + vnode_id *vnid); + +int fs_opendir(fs_nspace *ns, fs_node *node, btCookie **cookie); +int fs_closedir(fs_nspace *ns, fs_node *node, btCookie *cookie); +int fs_rewinddir(fs_nspace *ns, fs_node *node, btCookie *cookie); +int fs_readdir(fs_nspace *ns, fs_node *node, btCookie *cookie, long *num, + struct dirent *buf, size_t bufsize); + +int fs_free_dircookie(fs_nspace *ns, fs_node *node, btCookie *cookie); +int fs_rstat(fs_nspace *ns, fs_node *node, struct stat *); +int fs_mount(nspace_id nsid, const char *devname, ulong flags, + struct mount_bt_params *parms, size_t len, fs_nspace **data, vnode_id *vnid); +int fs_unmount(fs_nspace *ns); +int fs_rfsstat(fs_nspace *ns, struct fs_info *); + +int fs_open(fs_nspace *ns, fs_node *node, int omode, fs_file_cookie **cookie); +int fs_close(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie); +int fs_free_cookie(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie); +int fs_read(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, void *buf, + size_t *len); + +int fs_write(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, + const void *buf, size_t *len); + +int fs_wstat(fs_nspace *ns, fs_node *node, struct stat *, long mask); +int fs_wfsstat(fs_nspace *ns, struct fs_info *, long mask); +int fs_create(fs_nspace *ns, fs_node *dir, const char *name, + int omode, int perms, vnode_id *vnid, fs_file_cookie **cookie); + +int fs_unlink(fs_nspace *ns, fs_node *dir, const char *name); +int fs_remove_vnode(fs_nspace *ns, fs_node *node, char r); +int fs_secure_vnode(fs_nspace *ns, fs_node *node); + +int fs_mkdir(fs_nspace *ns, fs_node *dir, const char *name, int perms); + +int fs_rename(fs_nspace *ns, fs_node *olddir, const char *oldname, + fs_node *newdir, const char *newname); + +int fs_rmdir(fs_nspace *ns, fs_node *dir, const char *name); +int fs_readlink(fs_nspace *ns, fs_node *node, char *buf, size_t *bufsize); + +int fs_symlink(fs_nspace *ns, fs_node *dir, const char *name, + const char *path); + +extern void insert_node(fs_nspace *ns, fs_node *node); +extern void remove_node(fs_nspace *ns, vnode_id vnid); + +extern int fs_access(void *ns, void *node, int mode); + +extern int fs_read_attrib(fs_nspace *ns, fs_node *node, const char *name, int type, void *buf, size_t *len, off_t pos); +extern int fs_write_attrib(fs_nspace *ns, fs_node *node, const char *name, int type, const void *buf, size_t *len, off_t pos); +extern int fs_open_attribdir(fs_nspace *ns, fs_node *node, btCookie **cookie); +extern int fs_close_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie); +extern int fs_rewind_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie); +extern int fs_read_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize); +extern int fs_remove_attrib(fs_nspace *ns, fs_node *node, const char *name); +extern int fs_stat_attrib(fs_nspace *ns, fs_node *node, const char *name, struct attr_info *buf); + +extern int fs_open_indexdir(fs_nspace *ns, btCookie **cookie); +extern int fs_close_indexdir(fs_nspace *ns, btCookie *cookie); +extern int fs_rewind_indexdir(fs_nspace *ns, btCookie *cookie); +extern int fs_read_indexdir(fs_nspace *ns, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize); +extern int fs_free_indexdircookie(fs_nspace *ns, btCookie *cookie); +extern int fsCreateIndex(fs_nspace *ns, const char *name, int type, int flags); +extern int fsRemoveIndex(fs_nspace *ns, const char *name); +extern int fsStatIndex(fs_nspace *ns, const char *name, struct index_info *buf); + +enum +{ + C_ERROR_STALE=B_ERRORS_END+1 +}; + +#define USE_SYSTEM_AUTHENTICATION 1 + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/fsproto.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/fsproto.h new file mode 100644 index 0000000000..a6072837d5 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/fsproto.h @@ -0,0 +1,246 @@ +#ifndef _FSPROTO_H +#define _FSPROTO_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef dev_t nspace_id; +typedef ino_t vnode_id; + +/* UGLY UGLY UGLY */ +#ifndef _DRIVERS_H +struct selectsync; +typedef struct selectsync selectsync; +#endif + + +/* + * PUBLIC PART OF THE FILE SYSTEM PROTOCOL + */ + +#define WSTAT_MODE 0x0001 +#define WSTAT_UID 0x0002 +#define WSTAT_GID 0x0004 +#define WSTAT_SIZE 0x0008 +#define WSTAT_ATIME 0x0010 +#define WSTAT_MTIME 0x0020 +#define WSTAT_CRTIME 0x0040 + +#define WFSSTAT_NAME 0x0001 + +#define B_ENTRY_CREATED 1 +#define B_ENTRY_REMOVED 2 +#define B_ENTRY_MOVED 3 +#define B_STAT_CHANGED 4 +#define B_ATTR_CHANGED 5 +#define B_DEVICE_MOUNTED 6 +#define B_DEVICE_UNMOUNTED 7 + +#define B_STOP_WATCHING 0x0000 +#define B_WATCH_NAME 0x0001 +#define B_WATCH_STAT 0x0002 +#define B_WATCH_ATTR 0x0004 +#define B_WATCH_DIRECTORY 0x0008 + +#define SELECT_READ 1 +#define SELECT_WRITE 2 +#define SELECT_EXCEPTION 3 + +#define B_CUR_FS_API_VERSION 2 + +struct attr_info; +struct index_info; + +typedef int op_read_vnode(void *ns, vnode_id vnid, char r, void **node); +typedef int op_write_vnode(void *ns, void *node, char r); +typedef int op_remove_vnode(void *ns, void *node, char r); +typedef int op_secure_vnode(void *ns, void *node); + +typedef int op_walk(void *ns, void *base, const char *file, char **newpath, + vnode_id *vnid); + +typedef int op_access(void *ns, void *node, int mode); + +typedef int op_create(void *ns, void *dir, const char *name, + int omode, int perms, vnode_id *vnid, void **cookie); +typedef int op_mkdir(void *ns, void *dir, const char *name, int perms); +typedef int op_symlink(void *ns, void *dir, const char *name, + const char *path); +typedef int op_link(void *ns, void *dir, const char *name, void *node); + +typedef int op_rename(void *ns, void *olddir, const char *oldname, + void *newdir, const char *newname); +typedef int op_unlink(void *ns, void *dir, const char *name); +typedef int op_rmdir(void *ns, void *dir, const char *name); + +typedef int op_readlink(void *ns, void *node, char *buf, size_t *bufsize); + +typedef int op_opendir(void *ns, void *node, void **cookie); +typedef int op_closedir(void *ns, void *node, void *cookie); +typedef int op_rewinddir(void *ns, void *node, void *cookie); +typedef int op_readdir(void *ns, void *node, void *cookie, long *num, + struct dirent *buf, size_t bufsize); + +typedef int op_open(void *ns, void *node, int omode, void **cookie); +typedef int op_close(void *ns, void *node, void *cookie); +typedef int op_free_cookie(void *ns, void *node, void *cookie); +typedef int op_read(void *ns, void *node, void *cookie, off_t pos, void *buf, + size_t *len); +typedef int op_write(void *ns, void *node, void *cookie, off_t pos, + const void *buf, size_t *len); +typedef int op_readv(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, + size_t count, size_t *len); +typedef int op_writev(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, + size_t count, size_t *len); +typedef int op_ioctl(void *ns, void *node, void *cookie, int cmd, void *buf, + size_t len); +typedef int op_setflags(void *ns, void *node, void *cookie, int flags); + +typedef int op_rstat(void *ns, void *node, struct stat *); +typedef int op_wstat(void *ns, void *node, struct stat *, long mask); +typedef int op_fsync(void *ns, void *node); + +typedef int op_select(void *ns, void *node, void *cookie, uint8 event, + uint32 ref, selectsync *sync); +typedef int op_deselect(void *ns, void *node, void *cookie, uint8 event, + selectsync *sync); + +typedef int op_initialize(const char *devname, void *parms, size_t len); +typedef int op_mount(nspace_id nsid, const char *devname, ulong flags, + void *parms, size_t len, void **data, vnode_id *vnid); +typedef int op_unmount(void *ns); +typedef int op_sync(void *ns); +typedef int op_rfsstat(void *ns, struct fs_info *); +typedef int op_wfsstat(void *ns, struct fs_info *, long mask); + + +typedef int op_open_attrdir(void *ns, void *node, void **cookie); +typedef int op_close_attrdir(void *ns, void *node, void *cookie); +typedef int op_rewind_attrdir(void *ns, void *node, void *cookie); +typedef int op_read_attrdir(void *ns, void *node, void *cookie, long *num, + struct dirent *buf, size_t bufsize); +typedef int op_remove_attr(void *ns, void *node, const char *name); +typedef int op_rename_attr(void *ns, void *node, const char *oldname, + const char *newname); +typedef int op_stat_attr(void *ns, void *node, const char *name, + struct attr_info *buf); + +typedef int op_write_attr(void *ns, void *node, const char *name, int type, + const void *buf, size_t *len, off_t pos); +typedef int op_read_attr(void *ns, void *node, const char *name, int type, + void *buf, size_t *len, off_t pos); + +typedef int op_open_indexdir(void *ns, void **cookie); +typedef int op_close_indexdir(void *ns, void *cookie); +typedef int op_rewind_indexdir(void *ns, void *cookie); +typedef int op_read_indexdir(void *ns, void *cookie, long *num, + struct dirent *buf, size_t bufsize); +typedef int op_create_index(void *ns, const char *name, int type, int flags); +typedef int op_remove_index(void *ns, const char *name); +typedef int op_rename_index(void *ns, const char *oldname, + const char *newname); +typedef int op_stat_index(void *ns, const char *name, struct index_info *buf); + +typedef int op_open_query(void *ns, const char *query, ulong flags, + port_id port, long token, void **cookie); +typedef int op_close_query(void *ns, void *cookie); +typedef int op_read_query(void *ns, void *cookie, long *num, + struct dirent *buf, size_t bufsize); + +typedef struct vnode_ops { + op_read_vnode (*read_vnode); + op_write_vnode (*write_vnode); + op_remove_vnode (*remove_vnode); + op_secure_vnode (*secure_vnode); + op_walk (*walk); + op_access (*access); + op_create (*create); + op_mkdir (*mkdir); + op_symlink (*symlink); + op_link (*link); + op_rename (*rename); + op_unlink (*unlink); + op_rmdir (*rmdir); + op_readlink (*readlink); + op_opendir (*opendir); + op_closedir (*closedir); + op_free_cookie (*free_dircookie); + op_rewinddir (*rewinddir); + op_readdir (*readdir); + op_open (*open); + op_close (*close); + op_free_cookie (*free_cookie); + op_read (*read); + op_write (*write); + op_readv (*readv); + op_writev (*writev); + op_ioctl (*ioctl); + op_setflags (*setflags); + op_rstat (*rstat); + op_wstat (*wstat); + op_fsync (*fsync); + op_initialize (*initialize); + op_mount (*mount); + op_unmount (*unmount); + op_sync (*sync); + op_rfsstat (*rfsstat); + op_wfsstat (*wfsstat); + op_select (*select); + op_deselect (*deselect); + op_open_indexdir (*open_indexdir); + op_close_indexdir (*close_indexdir); + op_free_cookie (*free_indexdircookie); + op_rewind_indexdir (*rewind_indexdir); + op_read_indexdir (*read_indexdir); + op_create_index (*create_index); + op_remove_index (*remove_index); + op_rename_index (*rename_index); + op_stat_index (*stat_index); + op_open_attrdir (*open_attrdir); + op_close_attrdir (*close_attrdir); + op_free_cookie (*free_attrdircookie); + op_rewind_attrdir (*rewind_attrdir); + op_read_attrdir (*read_attrdir); + op_write_attr (*write_attr); + op_read_attr (*read_attr); + op_remove_attr (*remove_attr); + op_rename_attr (*rename_attr); + op_stat_attr (*stat_attr); + op_open_query (*open_query); + op_close_query (*close_query); + op_free_cookie (*free_querycookie); + op_read_query (*read_query); +} vnode_ops; + +extern _IMPEXP_KERNEL int new_path(const char *path, char **copy); +extern _IMPEXP_KERNEL void free_path(char *p); + +extern _IMPEXP_KERNEL int notify_listener(int op, nspace_id nsid, + vnode_id vnida, vnode_id vnidb, + vnode_id vnidc, const char *name); +extern _IMPEXP_KERNEL void notify_select_event(selectsync *sync, uint32 ref); +extern _IMPEXP_KERNEL int send_notification(port_id port, long token, + ulong what, long op, nspace_id nsida, + nspace_id nsidb, vnode_id vnida, + vnode_id vnidb, vnode_id vnidc, + const char *name); +extern _IMPEXP_KERNEL int get_vnode(nspace_id nsid, vnode_id vnid, void **data); +extern _IMPEXP_KERNEL int put_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int new_vnode(nspace_id nsid, vnode_id vnid, void *data); +extern _IMPEXP_KERNEL int remove_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int unremove_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int is_vnode_removed(nspace_id nsid, vnode_id vnid); + + +extern _EXPORT vnode_ops fs_entry; +extern _EXPORT int32 api_version; + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/ksocket_internal.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/ksocket_internal.h new file mode 100644 index 0000000000..e44e55c7b8 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/ksocket_internal.h @@ -0,0 +1,166 @@ +#ifndef _KSOCKET_INTERNAL_H + +#define _KSOCKET_INTERNAL_H + +#include + +struct ks_param_header +{ + port_id port; +}; + +struct ks_reply_header +{ + int error; +}; + +struct ks_socket_param +{ + struct ks_param_header header; + int family,type,proto; +}; + +struct ks_socket_reply +{ + struct ks_reply_header header; + int result; +}; + +struct ks_bind_param +{ + struct ks_param_header header; + int fd; + int size; + char addr[1]; +}; + +struct ks_bind_reply +{ + struct ks_reply_header header; + int result; +}; + +struct ks_getsockname_param +{ + struct ks_param_header header; + int fd; + int size; +}; + +struct ks_getsockname_reply +{ + struct ks_reply_header header; + int result; + int size; + char addr[1]; +}; + +struct ks_recvfrom_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; + int fromlen; +}; + +struct ks_recvfrom_reply +{ + struct ks_reply_header header; + ssize_t result; + int fromlen; + char data[1]; +}; + +struct ks_sendto_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; + int tolen; + char data[1]; +}; + +struct ks_sendto_reply +{ + struct ks_reply_header header; + ssize_t result; +}; + +struct ks_recv_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; +}; + +struct ks_recv_reply +{ + struct ks_reply_header header; + ssize_t result; + char data[1]; +}; + +struct ks_send_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; + char data[1]; +}; + +struct ks_send_reply +{ + struct ks_reply_header header; + ssize_t result; +}; + +struct ks_listen_param +{ + struct ks_param_header header; + int fd,backlog; +}; + +struct ks_listen_reply +{ + struct ks_reply_header header; + int result; +}; + +struct ks_closesocket_param +{ + struct ks_param_header header; + int fd; +}; + +struct ks_closesocket_reply +{ + struct ks_reply_header header; + int result; +}; + +enum +{ + KS_SOCKET, + KS_BIND, + KS_GETSOCKNAME, + KS_GETPEERNAME, + KS_CONNECT, + KS_ACCEPT, + KS_RECVFROM, + KS_SENDTO, + KS_RECV, + KS_SEND, + KS_LISTEN, + KS_CLOSESOCKET, + KS_MESSAGE, + KS_QUIT +}; + +#define KSOCKET_DAEMON_NAME "ksocket_daemon" +#define KSOCKETD_SIGNATURE "application/x-vnd.BareCode-ksocketd" + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/md5.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/md5.h new file mode 100644 index 0000000000..4148570cd7 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/md5.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id: md5.h $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This code has some adaptations for the Ghostscript environment, but it + * will compile and run correctly in any environment with 8-bit chars and + * 32-bit ints. Specifically, it assumes that if the following are + * defined, they have the same meaning as in Ghostscript: P1, P2, P3, + * ARCH_IS_BIG_ENDIAN. + */ + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE void md5EncodeString(const char *source, char *dest); + +/* Initialize the algorithm. */ +#ifdef P1 +void md5_init(P1(md5_state_t *pms)); +#else +void md5_init(md5_state_t *pms); +#endif + +/* Append a string to the message. */ +#ifdef P3 +void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); +#else +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +#endif + +/* Finish the message and return the digest. */ +#ifdef P2 +void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); +#else +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/rpc.cpp b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/rpc.cpp new file mode 100644 index 0000000000..ba38ddaff2 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/rpc.cpp @@ -0,0 +1,471 @@ +#include "betalk.h" +#include "sysdepdefs.h" +#include "rpc.h" + +#include "signal.h" + + +int btRPCConnect(unsigned int serverIP, int port) +{ + struct sockaddr_in serverAddr; + int session; + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(port); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(serverIP); + + // Create a new socket to receive incoming requests. + session = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (session == INVALID_SOCKET) + return INVALID_SOCKET; + + // Bind that socket to the address constructed above. + if (connect(session, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return INVALID_SOCKET; + + return session; +} + +bool btRPCSend(int session, bt_outPacket *outPacket) +{ + // The XID will be 0. + btRPCPutInt32(outPacket, 0); + btRPCPutChar(outPacket, BT_CMD_TERMINATOR); + + if (btSendMsg(session, outPacket->buffer, outPacket->length, 0) == -1) + return false; + + return true; +} + +bool btRPCCheckSignature(int session) +{ + char signature[20]; + unsigned int sigLen; + + sigLen = strlen(BT_RPC_SIGNATURE); + memset(signature, 0, sigLen); + if (btRecvMsg(session, signature, sigLen, 0) == -1) + return false; + + // Check the signature's validity. + signature[sigLen] = 0; + return (strcmp(signature, BT_RPC_SIGNATURE) == 0); +} + +// btRPCSimpleCall() +// +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket) +{ + struct timeval timeout; + bt_inPacket *inPacket; + fd_set sockSet; + char *buffer; + int session; + int32 xid, length; + + // Establish a connection with the requested server, on the requested port. + // If we can't connect, abort and return a NULL packet. + inPacket = NULL; + session = btRPCConnect(serverIP, port); + if (session == INVALID_SOCKET) + return NULL; + + // If we connected, send the requested RPC packet. If the packet cannot be + // sent, the connection has dropped and we'll abort the call. + if (!btRPCSend(session, outPacket)) + { + closesocket(session); + return NULL; + } + + // Set a reasonable timeout period. Select() is used in leiu of alarm() because + // select() also aborts on error, alarm() effects all threads in a process. + FD_ZERO(&sockSet); + timeout.tv_sec = 8; + timeout.tv_usec = 0; + + // Block in select() waiting for activity. This will block until data is available + // or until a socket error is pending. + FD_SET(session, &sockSet); + select(session + 1, &sockSet, NULL, NULL, &timeout); + + // If our socket has data pending, then read the incoming RPC response packet. + // This should consist of a valid RPC signature, a tranaction ID (xid), the length + // of the variable data, and the data itself. + if (FD_ISSET(session, &sockSet)) + if (btRPCCheckSignature(session)) + { + if (btRecvMsg(session, &xid, sizeof(int32), 0) == -1 || + btRecvMsg(session, &length, sizeof(int32), 0) == -1) + goto abortCall; + + xid = B_LENDIAN_TO_HOST_INT32(xid); + length = B_LENDIAN_TO_HOST_INT32(length); + + // Now allocate a buffer of the appropriate length. If one cannot be + // allocated, we won't be able to store incoming information and the call + // must be aborted. + if (length > 0 && length < BT_RPC_MAX_PACKET_SIZE) + { + buffer = (char *) malloc(length + 1); + if (buffer) + { + // Read the remaining packet contents. The btRecv() function takes + // care of restarting the recv() when signal interrupts occur. It + // will always return -1 on error, even upon orderly shutdown of the peer. + if (btRecvMsg(session, buffer, length, 0) == -1) + { + free(buffer); + goto abortCall; + } + + // Terminate the buffer. + buffer[length] = 0; + + // Allocate a new incoming packet and set its buffer and length. + inPacket = (bt_inPacket *) malloc(sizeof(bt_inPacket)); + if (inPacket) + { + inPacket->buffer = buffer; + inPacket->length = length; + inPacket->offset = 0; + } + else + free(buffer); + } + } + } + + // Execution can naturally lead here or we can jump here from a failed attempt to + // send or receive an RPC packet. The socket is closed and the current incoming + // packet returned, which will be NULL upon failure. +abortCall: + shutdown(session, 2); + close(session); + return inPacket; +} + +int btRecvMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesRead = 0; + do + { + int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags); + if (bytes == -1) + return -1; + + bytesRead += bytes; + } while (bytesRead < dataLen); + + return bytesRead; +} + +// btRecv() +// +int btRecv(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = recv(sock, data, dataLen, flags); + if (bytes == 0) + return -1; + else if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +int btSendMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesSent = 0; + do + { + int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags); + if (bytes == -1) + return -1; + + bytesSent += bytes; + } while (bytesSent < dataLen); + + return bytesSent; +} + +// btSend() +// +int btSend(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = send(sock, data, dataLen, flags); + if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +void btDestroyInPacket(bt_inPacket *packet) +{ + if (packet) + { + if (packet->buffer) + free(packet->buffer); + + free(packet); + } +} + +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length) +{ + bt_outPacket *packet; + + packet = (bt_outPacket *) malloc(sizeof(bt_outPacket)); + if (!packet) + return NULL; + + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + { + free(packet); + return NULL; + } + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + +// btRPCPutChar(packet, BT_RPC_VERSION_HI); +// btRPCPutChar(packet, BT_RPC_VERSION_LO); + btRPCPutInt32(packet, 7 + (8 * argc) + length); + btRPCPutChar(packet, command); + btRPCPutChar(packet, argc); + + return packet; +} + +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length) +{ + btRPCPutInt32(packet, type); + btRPCPutInt32(packet, length); + btRPCPutBinary(packet, data, length); +} + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error, int length) +{ + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + return; + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + btRPCPutInt32(packet, xid); + btRPCPutInt32(packet, 0); + btRPCPutInt32(packet, error); +} + +void btRPCSendAck(int client, bt_outPacket *packet) +{ + if (packet) + if (packet->buffer) + { + *(int32 *)(&packet->buffer[9]) = B_HOST_TO_LENDIAN_INT32(packet->length - 13); + btSendMsg(client, packet->buffer, packet->length, 0); + free(packet->buffer); + } +} + +unsigned char btRPCGetChar(bt_inPacket *packet) +{ + unsigned char value; + + if (packet->offset < packet->length) + value = (unsigned char) packet->buffer[packet->offset]; + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + if (bytes > 0) + memcpy(str, &packet->buffer[packet->offset], bytes); + + str[bytes] = 0; + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return ERANGE; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return ERANGE; + + if (length < bytes) + return ERANGE; + + if (bytes > 0) + memcpy(buffer, &packet->buffer[packet->offset], bytes); + + packet->offset += bytes; + return bytes; +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +int btRPCGetStat(bt_inPacket *packet, struct stat *st) +{ + st->st_dev = 0; + st->st_nlink = btRPCGetInt32(packet); + st->st_uid = btRPCGetInt32(packet); + st->st_gid = btRPCGetInt32(packet); + st->st_size = btRPCGetInt64(packet); + st->st_blksize = btRPCGetInt32(packet); + st->st_rdev = btRPCGetInt32(packet); + st->st_ino = btRPCGetInt64(packet); + st->st_mode = btRPCGetInt32(packet); + st->st_atime = btRPCGetInt32(packet); + st->st_mtime = btRPCGetInt32(packet); + st->st_ctime = btRPCGetInt32(packet); +} + +void btRPCPutStat(bt_outPacket *packet, struct stat *st) +{ + if (packet && st) + { + btRPCPutInt32(packet, (int) st->st_nlink); + btRPCPutInt32(packet, (int) st->st_uid); + btRPCPutInt32(packet, (int) st->st_gid); + btRPCPutInt64(packet, (int64) st->st_size); + btRPCPutInt32(packet, (int) st->st_blksize); + btRPCPutInt32(packet, (int) st->st_rdev); + btRPCPutInt64(packet, (int64) st->st_ino); + btRPCPutInt32(packet, (int) st->st_mode); + btRPCPutInt32(packet, (int) st->st_atime); + btRPCPutInt32(packet, (int) st->st_mtime); + btRPCPutInt32(packet, (int) st->st_ctime); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/rpc.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/rpc.h new file mode 100644 index 0000000000..89c1194d2b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/rpc.h @@ -0,0 +1,25 @@ +// rpc.h + +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket); +int btRPCConnect(unsigned int serverIP, int port); +bool btRPCSend(int session, bt_outPacket *outPacket); +bool btRPCCheckSignature(int session); +void btDestroyInPacket(bt_inPacket *packet); +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error, int length); +void btRPCSendAck(int client, bt_outPacket *packet); +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char *btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +void btRPCGrowPacket(bt_outPacket *packet, int bytes); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/sysdepdefs.h b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/sysdepdefs.h new file mode 100644 index 0000000000..6bb4bd5051 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/MyNetwork/sysdepdefs.h @@ -0,0 +1,10 @@ +#ifndef _SYSDEPDEFS_H_ +#define _SYSDEPDEFS_H_ + +#ifdef BONE_VERSION + +#define closesocket(s) close(s) + +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/beserved_server.c b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/beserved_server.c new file mode 100644 index 0000000000..0e3fce26e6 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/beserved_server.c @@ -0,0 +1,2678 @@ +// btAdd.cpp : Defines the entry point for the console application. +// + +// To-do: +// +// 1.0.67 +// X Auto-mount from My Network +// _ BONE-compliance +// X Better reconnect logic +// X INT and TERM signal handlers +// X Lingering buffer mechanism +// X Test for duplicate share names defined in settings file +// +// 1.0.68 (stability) +// _ Fix problems with share browsing +// _ Fix duplicate vnid problem +// X Fix large file write problem +// X Correct crash during unmount process +// _ Packet buffer allocation/de-allocation cleanup +// _ Query capabilities +// _ Ability to mount multiple shares +// _ Node monitoring +// +// 1.0.69 (security) +// _ Don't allow following links outside the shared folder +// _ Make a file share read-only +// _ Restart of server erases inode-to-filename map +// +// Long-term +// _ Ability to reconnect shares at login +// _ Preferences application for defining file shares +// + +// Potential Uses: +// 1. Domain server, keeping track of users for logging in +// 2. File server, to share BeOS volume files across a network +// 3. Document management, to store documents with attributes +// 4. Version Control System, to manage multiple versions of documents +// 5. General directory server, for local or network settings and information + +#include "FindDirectory.h" + +#include "betalk.h" +#include "fsproto.h" +#include "netdb.h" + +#include "utime.h" +#include "ctype.h" +#include "time.h" +#include "signal.h" + +#define BT_MAX_THREADS 100 +#define BT_MAX_RETRIES 3 +#define BT_MAX_FILE_SHARES 128 + +#define BT_MAIN_NAME "BeServed Daemon" +#define BT_THREAD_NAME "BeServed Handler" +#define BT_HOST_THREAD_NAME "BeServed Host Publisher" +#define BT_SIGNATURE "application/x-vnd.Teldar-BeServed" + +#define PATH_ROOT "/boot" +#define PATH_DELIMITER '/' + +#ifndef iswhite +#define iswhite(c) ((c == ' ' || c == '\t')) +#endif + +typedef struct +{ + unsigned int type; + unsigned int length; + char *data; +} bt_arg_t; + +typedef struct session +{ + int socket; + unsigned int s_addr; + thread_id handlerID; + + // What share did the client connect to? + int share; + + char ioBuffer[BT_MAX_IO_BUFFER + 1]; + char attrBuffer[BT_MAX_ATTR_BUFFER + 1]; + char pathBuffer[B_PATH_NAME_LENGTH]; +} bt_session_t; + +typedef void (*bt_net_func)(bt_session_t *, unsigned int, int, bt_arg_t *); + +typedef struct dirCommand +{ + unsigned char command; + bt_net_func handler; +} bt_command_t; + +typedef struct +{ + vnode_id vnid; + int shareId; + char unused[20]; +} bt_fdesc; + +typedef struct btnode +{ + vnode_id vnid; + char name[100]; + int refCount; + struct btnode *next; + struct btnode *prev; + struct btnode *parent; +} bt_node; + +typedef struct fileShare +{ + char path[B_PATH_NAME_LENGTH]; + char name[B_FILE_NAME_LENGTH]; + bool used; + bool readOnly; + struct fileShare *next; +} bt_fileShare_t; + +bt_node *rootNode = NULL; + + +int main(int argc, char *argv[]); +bool dateCheck(); +int32 btSendHost(void *data); +void startService(); +void endService(int sig); +void initSessions(); +void initShares(); +void getFileShare(const char *buffer); +int receiveRequest(bt_session_t *session); +void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]); +void launchThread(int client, struct sockaddr_in *addr); +int tooManyConnections(unsigned int s_addr); +void sendErrorToClient(int client, int error); +void printToClient(int client, char *format, ...); +void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command); +int32 requestThread(void *data); +int copyFile(char *source, char *dest); +int stricmp(char *str1, char *str2); + +bt_node *btGetNodeFromVnid(vnode_id vnid); +void btAddHandle(bt_fdesc *dhandle, bt_fdesc *fhandle, char *name); +void btRemoveHandle(bt_fdesc *fhandle); +void btPurgeNodes(bt_fdesc *fdesc); +void btRemoveNode(bt_node *deadNode); +bool btIsAncestorNode(vnode_id vnid, bt_node *node); +char *btGetLocalFileName(char *path, bt_fdesc *fhandle); +void btMakeHandleFromNode(bt_node *node, bt_fdesc *fdesc); +bt_node *btFindNode(bt_node *parent, char *fileName); +char *btGetSharePath(char *shareName); +int btGetShareId(char *shareName); +void btGetRootPath(vnode_id vnid, char *path); +void btLock(sem_id semaphore, int32 *atomic); +void btUnlock(sem_id semaphore, int32 *atomic); + +int btMount(char *shareName, btFileHandle *fhandle); +int btGetFSInfo(fs_info *fsInfo); +int btLookup(char *pathBuf, bt_fdesc *ddesc, char *fileName, bt_fdesc *fdesc); +int btStat(char *pathBuf, bt_fdesc *fdesc, struct stat *st); +int btReadDir(char *pathBuf, bt_fdesc *ddesc, DIR **dir, bt_fdesc *fdesc, char *filename, struct stat *st); +int32 btRead(char *pathBuf, bt_fdesc *fdesc, off_t pos, int32 len, char *buffer); +int32 btWrite(char *pathBuf, bt_fdesc *fdesc, off_t pos, int32 len, char *buffer); +int btCreate(char *pathBuf, bt_fdesc *ddesc, char *name, int omode, int perms, bt_fdesc *fdesc); +int btTruncate(char *pathBuf, bt_fdesc *fdesc, int64 len); +int btCreateDir(char *pathBuf, bt_fdesc *ddesc, char *name, int perms, bt_fdesc *fdesc, struct stat *st); +int btDeleteDir(char *pathBuf, bt_fdesc *ddesc, char *name); +int btRename(char *pathBuf, bt_fdesc *oldfdesc, char *oldName, bt_fdesc *newfdesc, char *newName); +int btUnlink(char *pathBuf, bt_fdesc *ddesc, char *name); +int btReadLink(char *pathBuf, bt_fdesc *fdesc, char *buffer, int length); +int btSymLink(char *pathBuf, bt_fdesc *fdesc, char *name, char *dest); +int btWStat(char *pathBuf, bt_fdesc *fdesc, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime); +int btReadAttrib(char *pathBuf, bt_fdesc *fdesc, char *name, int32 dataType, void *buffer, int32 pos, int32 len); +int btWriteAttrib(char *pathBuf, bt_fdesc *fdesc, char *name, int32 dataType, void *buffer, int32 pos, int32 len); +int btReadAttribDir(char *pathBuf, bt_fdesc *fdesc, DIR **dir, char *attrName); +int btRemoveAttrib(char *pathBuf, bt_fdesc *fdesc, char *name); +int btStatAttrib(char *pathBuf, bt_fdesc *fdesc, char *name, struct attr_info *info); +int btReadIndexDir(DIR **dir, char *indexName); +int btCreateIndex(char *name, int type, int flags); +int btRemoveIndex(char *name); +int btStatIndex(char *name, struct index_info *info); +int btReadQuery(DIR **dir, char *query, char *fileName, int64 *inode); + +void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); + +bt_session_t sessions[BT_MAX_THREADS]; +bt_fileShare_t fileShares[BT_MAX_FILE_SHARES]; +bool running = true; +int server; +thread_id hostThread; +sem_id handleSem; +int32 handleVar; + +bt_command_t dirCommands[] = +{ + { BT_CMD_MOUNT, netbtMount }, + { BT_CMD_FSINFO, netbtFSInfo }, + { BT_CMD_LOOKUP, netbtLookup }, + { BT_CMD_STAT, netbtStat }, + { BT_CMD_READDIR, netbtReadDir }, + { BT_CMD_READ, netbtRead }, + { BT_CMD_WRITE, netbtWrite }, + { BT_CMD_CREATE, netbtCreate }, + { BT_CMD_TRUNCATE, netbtTruncate }, + { BT_CMD_MKDIR, netbtCreateDir }, + { BT_CMD_RMDIR, netbtDeleteDir }, + { BT_CMD_RENAME, netbtRename }, + { BT_CMD_UNLINK, netbtUnlink }, + { BT_CMD_READLINK, netbtReadLink }, + { BT_CMD_SYMLINK, netbtSymLink }, + { BT_CMD_WSTAT, netbtWStat }, + { BT_CMD_READATTRIB, netbtReadAttrib }, + { BT_CMD_WRITEATTRIB, netbtWriteAttrib }, + { BT_CMD_READATTRIBDIR, netbtReadAttribDir }, + { BT_CMD_REMOVEATTRIB, netbtRemoveAttrib }, + { BT_CMD_STATATTRIB, netbtStatAttrib }, + { BT_CMD_READINDEXDIR, netbtReadIndexDir }, + { BT_CMD_CREATEINDEX, netbtCreateIndex }, + { BT_CMD_REMOVEINDEX, netbtRemoveIndex }, + { BT_CMD_STATINDEX, netbtStatIndex }, + { BT_CMD_READQUERY, netbtReadQuery }, + { BT_CMD_QUIT, netbtQuit }, + { 0, NULL } +}; + +/*---------------------------------------------------------------- +class BeServedServer : public BApplication +{ + thread_id appThread; + bool running; + + public: + BeServedServer(const char *signature); + + virtual void ReadyToRun(); + virtual bool QuitRequested(); +}; + +BeServedServer::BeServedServer(const char *signature) + : BApplication(signature) +{ +} + +void BeServedServer::ReadyToRun() +{ + running = true; + appThread = spawn_thread(appMain, BT_MAIN_NAME, B_NORMAL_PRIORITY, this); + resume_thread(appThread); +} + +bool BeServedServer::QuitRequested() +{ + status_t result; + + if (!BApplication::QuitRequested()) + return false; + + running = false; + wait_for_thread(appThread, &result); + return true; +} + +int main(int argc, char *argv[]) +{ + BeServedServer app(BT_SIGNATURE); + app.Run(); + return 0; +} +----------------------------------------------------------------------*/ +int main(int argc, char *argv[]) +{ + if (!dateCheck()) + return 0; + + initSessions(); + initShares(); + signal(SIGINT, endService); + signal(SIGTERM, endService); + + if ((handleSem = create_sem(0, "File Handle Semaphore")) > B_OK) + { + hostThread = spawn_thread(btSendHost, BT_HOST_THREAD_NAME, B_NORMAL_PRIORITY, 0); + resume_thread(hostThread); + + // Run the daemon. We will not return until the service is being + // stopped. + startService(); + + if (hostThread > 0) + kill_thread(hostThread); + + if (handleSem > 0) + delete_sem(handleSem); + } + + return 0; +} + +bool dateCheck() +{ + struct stat st; + time_t curTime; + + time(&curTime); + if (curTime > 999491300) + return false; + + if (stat("/boot/home/config/servers/beserved_server", &st) == 0) + if (curTime < st.st_ctime || curTime > st.st_ctime + 5184000) + return false; + + return true; +} + +int32 btSendHost(void *data) +{ + struct sockaddr_in serverAddr, clientAddr; + char buffer[4096]; + int i, server, addrLen, bufLen; + + buffer[0] = 0; + bufLen = sizeof(buffer); + + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(BT_QUERYHOST_PORT); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + server = socket(AF_INET, SOCK_DGRAM, 0); + if (server == INVALID_SOCKET) + return -1; + + // Bind that socket to the address constructed above. + if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return -1; + + while (running) + { + addrLen = sizeof(struct sockaddr_in); + recvfrom(server, buffer, bufLen - 1, 0, (struct sockaddr *) &clientAddr, &addrLen); + + if (strcmp(buffer, "btGetHost") == 0) + gethostname(buffer, bufLen); + else if (strcmp(buffer, "btGetShares") == 0) + { + buffer[0] = 0; + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + { + strcat(buffer, fileShares[i].name); + strcat(buffer, "/"); + } + } + else + continue; + + sendto(server, buffer, strlen(buffer), 0, (struct sockaddr *) &clientAddr, addrLen); + } + + // Close the socket. Technically, I believe we should call shutdown() + // first, but the BeOS header file socket.h indicates that this + // function is not currently working. It is present but may not have + // any effect. + shutdown(server, 2); + closesocket(server); + return 0; +} + +void initSessions() +{ + int i; + + for (i = 0; i < BT_MAX_THREADS; i++) + { + sessions[i].socket = INVALID_SOCKET; + sessions[i].handlerID = 0; + } +} + +void initShares() +{ + FILE *fp; + char path[B_PATH_NAME_LENGTH], buffer[512]; + int i, length; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + { + fileShares[i].name[0] = 0; + fileShares[i].path[0] = 0; + fileShares[i].used = false; + fileShares[i].readOnly = false; + fileShares[i].next = NULL; + } + + find_directory(B_COMMON_SETTINGS_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/BeServed-Settings"); + + fp = fopen(path, "r"); + if (fp) + { + while (fgets(buffer, sizeof(buffer) - 1, fp)) + { + length = strlen(buffer); + if (length <= 1 || buffer[0] == '#') + continue; + + if (buffer[length - 1] == '\n') + buffer[--length] = 0; + + if (strncmp(buffer, "share ", 6) == 0) + getFileShare(buffer); + } + + fclose(fp); + } +} + +void getFileShare(const char *buffer) +{ + struct stat st; + char path[B_PATH_NAME_LENGTH], share[B_FILE_NAME_LENGTH], *tok, *folder, delimiter; + int i; + + tok = (char *) buffer + (6 * sizeof(char)); + while (*tok && iswhite(*tok)) + tok++; + + if (!*tok) + return; + + if (*tok == '"') + { + delimiter = '"'; + tok++; + } + else + delimiter = ' '; + + i = 0; + while (*tok && *tok != delimiter) + path[i++] = *tok++; + + if (!*tok) + return; + + path[i] = 0; + while (*tok && iswhite(*tok)) + tok++; + + if (!*tok) + return; + + if (strncmp(tok, "as ", 3) != 0) + return; + + tok += 3; + while (*tok && iswhite(*tok)) + tok++; + + if (*tok == '"') + { + delimiter = '"'; + tok++; + } + else + delimiter = ' '; + + i = 0; + while (*tok && (isalnum(*tok) || (*tok == ' ' && delimiter == '"'))) + share[i++] = *tok++; + + if (i == 0) + return; + + // Now verify that the share name specified has not already been + // used to share another path. + share[i] = 0; + folder = btGetSharePath(share); + if (folder) + { + printf("%s already defined as %s\n", share, folder); + return; + } + + // Check the path to ensure its validity. + if (stat(path, &st) != 0) + return; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (!fileShares[i].used) + { + printf("Defining %s as %s\n", share, path); + strcpy(fileShares[i].name, share); + strcpy(fileShares[i].path, path); + fileShares[i].used = true; + return; + } + + printf("Share %s could not be defined (too many shares)\n", share); +} + +void startService() +{ + struct sockaddr_in serverAddr, clientAddr; + int client, addrLen; + char flags; + + // Store the length of the socket addressing structure for accept(). + addrLen = sizeof(struct sockaddr_in); + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(BT_TCPIP_PORT); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Create a new socket to receive incoming requests. + server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (server == INVALID_SOCKET) + return; + + // Set the socket option to reuse the current address in case it was + // in use by a prior version of the service that has not yet relinquished + // the socket. + flags = 1; + setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); + + // Bind that socket to the address constructed above. + if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return; + + // Listen for incoming connections. + if (listen(server, 5)) + return; + + // Continually accept incoming connections. When one is found, + // fire off a handler thread to accept commands. + while (running) + { + client = accept(server, (struct sockaddr *) &clientAddr, &addrLen); + if (client != INVALID_SOCKET) + launchThread(client, &clientAddr); + } + + // Close the socket. Technically, I believe we should call shutdown() + // first, but the BeOS header file socket.h indicates that this + // function is not currently working. It is present but may not have + // any effect. + shutdown(server, 2); + closesocket(server); + server = INVALID_SOCKET; +} + +void endService(int sig) +{ + if (hostThread > 0) + kill_thread(hostThread); + + if (handleSem > 0) + delete_sem(handleSem); + + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + exit(0); +} + +// launchThread() +// +void launchThread(int client, struct sockaddr_in *addr) +{ + int i, retry, found; + + // We need to find an available session for this connection. We don't + // want to create threads willy nilly until we bring down the OS, so we + // establish a pool of available sessions (threads) from which we must + // allocate with every request. + found = FALSE; + for (retry = 0; retry < BT_MAX_RETRIES && !found; retry++) + { + for (i = 0; i < BT_MAX_THREADS; i++) + if (sessions[i].socket == INVALID_SOCKET) + { + found = TRUE; + sessions[i].socket = client; + sessions[i].s_addr = addr->sin_addr.s_addr; + sessions[i].handlerID = + spawn_thread(requestThread, BT_THREAD_NAME, B_NORMAL_PRIORITY, &sessions[i]); + resume_thread(sessions[i].handlerID); + break; + } + + if (!found) + snooze(100000); + } + + if (!found) + { + sendErrorToClient(client, EBUSY); + shutdown(client, 2); + closesocket(client); + } +} + +int32 requestThread(void *data) +{ + bt_session_t *session = (bt_session_t *) data; + + if (!session) + return 0; + + while (receiveRequest(session)); + + shutdown(session->socket, 2); + closesocket(session->socket); + session->socket = INVALID_SOCKET; + return 0; +} + +int receiveRequest(bt_session_t *session) +{ + bt_inPacket packet; + char signature[20], *buffer; + unsigned char command; + int client, sigLen; + int32 bytesRead, length; + + client = session->socket; + + // Read the BeTalk RPC header. + sigLen = strlen(BT_RPC_SIGNATURE); + recv(client, signature, sigLen, 0); +// recv(client, &verHi, sizeof(verHi), 0); +// recv(client, &verLo, sizeof(verLo), 0); + + signature[sigLen] = 0; + if (strcmp(signature, BT_RPC_SIGNATURE)) + return 0; + + // Read in the rest of the packet. + recv(client, &length, sizeof(int32), 0); + if (length == 0 || length > BT_RPC_MAX_PACKET_SIZE) + return 0; + + buffer = (char *) malloc(length + 1); + if (!buffer) + return 0; + + bytesRead = 0; + do + { + bytesRead += recv(client, buffer + bytesRead, length - bytesRead, 0); + } while (bytesRead < length); + + buffer[length] = 0; + packet.buffer = buffer; + packet.length = length; + packet.offset = 0; + + // Read the transmission ID and command. + command = btRPCGetChar(&packet); + getArguments(session, &packet, command); + free(buffer); + return (command != BT_CMD_QUIT); +} + +void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command) +{ + bt_arg_t args[MAX_COMMAND_ARGS]; + int i, client; + bool error; + unsigned char argc, terminator; + int32 xid; + + error = false; + client = session->socket; + argc = btRPCGetChar(packet); + if (argc > MAX_COMMAND_ARGS) + return; + + for (i = 0; i < argc && !error; i++) + { + args[i].type = btRPCGetInt32(packet); + args[i].data = btRPCGetNewString(packet); + if (args[i].data == NULL) + error = true; + } + + if (!error) + { + xid = btRPCGetInt32(packet); + terminator = btRPCGetChar(packet); + if (terminator == BT_CMD_TERMINATOR) + handleRequest(session, xid, command, argc, args); + } + + while (--i >= 0) + free(args[i].data); +} + +void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]) +{ + int i; + + for (i = 0; dirCommands[i].handler; i++) + if (command == dirCommands[i].command) + { + (*dirCommands[i].handler)(session, xid, argc, argv); + return; + } + +// sendErrorToClient(sessions[sessionID].socket, E_BAD_COMMAND); +} + +void sendErrorToClient(int client, int error) +{ +// send(client, &error, sizeof(error), 0); +} + +void printToClient(int client, char *format, ...) +{ + va_list args; + char buffer[256]; + + va_start(args, format); + vsprintf(buffer, format, args); + va_end(args); + + send(client, buffer, strlen(buffer), 0); +} + +int copyFile(char *source, char *dest) +{ + FILE *srcFile, *dstFile; + int c; + + srcFile = fopen(source, "rb"); + if (srcFile == NULL) + return EACCES; + + dstFile = fopen(dest, "wb"); + if (dstFile == NULL) + { + fclose(srcFile); + return EACCES; + } + + while ((c = fgetc(srcFile)) != EOF) + fputc(c, dstFile); + + fclose(dstFile); + fclose(srcFile); + return B_OK; +} + +int stricmp(char *str1, char *str2) +{ + char *p1, *p2, c1, c2; + + for (p1 = str1, p2 = str2; *p1; p1++, p2++) + { + if (!*p2) + return 1; + + c1 = toupper(*p1); + c2 = toupper(*p2); + if (c1 < c2) + return -1; + else if (c1 > c2) + return 1; + } + + if (*p2) + return -1; + + return 0; +} + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error, int length) +{ + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + return; + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + btRPCPutInt32(packet, xid); + btRPCPutInt32(packet, 0); + btRPCPutInt32(packet, error); +} + +void btRPCSendAck(int client, bt_outPacket *packet) +{ + int32 bytesSent; + + if (packet) + if (packet->buffer) + { + *(int32 *)(&packet->buffer[9]) = packet->length - 13; + + bytesSent = 0; + do + { + bytesSent += send(client, packet->buffer + bytesSent, packet->length - bytesSent, 0); + } while (bytesSent < packet->length); + + free(packet->buffer); + } +} + +unsigned char btRPCGetChar(bt_inPacket *packet) +{ + unsigned char value; + + if (packet->offset < packet->length) + value = (unsigned char) packet->buffer[packet->offset]; + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = *((int32 *) &packet->buffer[packet->offset]); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = *((int64 *) &packet->buffer[packet->offset]); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = *((int32 *) &packet->buffer[packet->offset]); + packet->offset += sizeof(bytes); + if (!bytes) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + memcpy(str, &packet->buffer[packet->offset], bytes); + str[bytes] = 0; + + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return ERANGE; + + bytes = *((int32 *) &packet->buffer[packet->offset]); + packet->offset += sizeof(bytes); + if (!bytes) + return ERANGE; + + if (length < bytes) + return ERANGE; + + memcpy(buffer, &packet->buffer[packet->offset], bytes); + packet->offset += bytes; + return bytes; +} + +int btRPCGetHandle(bt_inPacket *packet, btFileHandle *fhandle) +{ + memcpy(fhandle->opaque, &packet->buffer[packet->offset], BT_FILE_HANDLE_SIZE); + packet->offset += BT_FILE_HANDLE_SIZE; + return B_OK; +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = value; + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = value; + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutHandle(bt_outPacket *packet, btFileHandle *fhandle) +{ + if (packet && fhandle) + { + btRPCGrowPacket(packet, BT_FILE_HANDLE_SIZE); + memcpy(&packet->buffer[packet->length], fhandle->opaque, BT_FILE_HANDLE_SIZE); + packet->length += BT_FILE_HANDLE_SIZE; + } +} + +int btRPCGetStat(bt_inPacket *packet, struct stat *st) +{ + st->st_dev = 0; + st->st_nlink = btRPCGetInt32(packet); + st->st_uid = btRPCGetInt32(packet); + st->st_gid = btRPCGetInt32(packet); + st->st_size = btRPCGetInt64(packet); + st->st_blksize = btRPCGetInt32(packet); + st->st_rdev = btRPCGetInt32(packet); + st->st_ino = btRPCGetInt64(packet); + st->st_mode = btRPCGetInt32(packet); + st->st_atime = btRPCGetInt32(packet); + st->st_mtime = btRPCGetInt32(packet); + st->st_ctime = btRPCGetInt32(packet); +} + +void btRPCPutStat(bt_outPacket *packet, struct stat *st) +{ + if (packet && st) + { + btRPCPutInt32(packet, (int) st->st_nlink); + btRPCPutInt32(packet, (int) st->st_uid); + btRPCPutInt32(packet, (int) st->st_gid); + btRPCPutInt64(packet, (int64) st->st_size); + btRPCPutInt32(packet, (int) st->st_blksize); + btRPCPutInt32(packet, (int) st->st_rdev); + btRPCPutInt64(packet, (int64) st->st_ino); + btRPCPutInt32(packet, (int) st->st_mode); + btRPCPutInt32(packet, (int) st->st_atime); + btRPCPutInt32(packet, (int) st->st_mtime); + btRPCPutInt32(packet, (int) st->st_ctime); + } +} + +//////////////////////////////////////////////////////////////////// + +bt_node *btGetNodeFromVnid(vnode_id vnid) +{ + bt_node *curNode = rootNode; + + while (curNode) + { + if (curNode->vnid == vnid) + break; + + curNode = curNode->next; + } + + return curNode; +} + +// btAddHandle() +// +void btAddHandle(bt_fdesc *dhandle, bt_fdesc *fhandle, char *name) +{ + bt_node *curNode, *lastNode; + + // We don't store the references to the current and the parent directory. + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + return; + + btLock(handleSem, &handleVar); + + // Move to the last node in the list. + curNode = lastNode = rootNode; + while (curNode) + { + lastNode = curNode; + curNode = curNode->next; + } + + // Allocate a new node. + curNode = (bt_node *) malloc(sizeof(bt_node)); + if (curNode == NULL) + { + btUnlock(handleSem, &handleVar); + return; + } + + // Copy over the name, vnid, and parent node. Obtaining the parent + // node requires scanning the list. + strcpy(curNode->name, name); + curNode->prev = lastNode; + curNode->next = NULL; + curNode->refCount = 0; + curNode->vnid = fhandle->vnid; + + // If we weren't provided with the directory node, then this must be + // the root node we're adding. + if (dhandle) + curNode->parent = btGetNodeFromVnid(dhandle->vnid); + else + curNode->parent = NULL; + + // If we didn't have a last node in the list, that means we're + // creating the first (or root) node. The global root node pointer + // needs to be updated accordingly. Otherwise, we just tack this + // item on to the end of the list. + if (lastNode == NULL) + rootNode = curNode; + else + lastNode->next = curNode; + + btUnlock(handleSem, &handleVar); +} + +// btRemoveHandle() +// +void btRemoveHandle(bt_fdesc *fhandle) +{ + bt_node *deadNode; + + btLock(handleSem, &handleVar); + + // Obtain the node in question. If no such node exists, then we + // probably have a bad handle. + deadNode = btGetNodeFromVnid(fhandle->vnid); + btRemoveNode(deadNode); + + btUnlock(handleSem, &handleVar); +} + +// btRemoveNode() +// +void btRemoveNode(bt_node *deadNode) +{ + if (deadNode) + { + // Make this entry's predecessor point to its successor. + if (deadNode->prev) + deadNode->prev->next = deadNode->next; + + // Make this entry's successor point to its predecessor. + if (deadNode->next) + deadNode->next->prev = deadNode->prev; + + // Now deallocate this node. + free(deadNode); + } +} + +// btPurgeNodes() +// +void btPurgeNodes(bt_fdesc *fdesc) +{ + bt_node *curNode; + vnode_id targetVnid; + + targetVnid = fdesc->vnid; + + btLock(handleSem, &handleVar); + + curNode = rootNode; + while (curNode) + { + if (curNode->vnid == targetVnid || btIsAncestorNode(targetVnid, curNode)) + btRemoveNode(curNode); + + curNode = curNode->next; + } + + btUnlock(handleSem, &handleVar); +} + +// btIsAncestorNode() +// +bool btIsAncestorNode(vnode_id vnid, bt_node *node) +{ + bt_node *curNode = node->parent; + + while (curNode) + { + if (curNode->vnid == vnid) + return true; + + curNode = curNode->parent; + } + + return false; +} + +// btGetLocalFileName() +// +char *btGetLocalFileName(char *path, bt_fdesc *fhandle) +{ + bt_node *node, *nodeStack[100]; + int stackSize; + + path[0] = 0; + stackSize = 1; + + btLock(handleSem, &handleVar); + + node = btGetNodeFromVnid(fhandle->vnid); + if (node == NULL) + { + btUnlock(handleSem, &handleVar); + return NULL; + } + + nodeStack[0] = node; + while ((node = node->parent) != NULL) + nodeStack[stackSize++] = node; + + btUnlock(handleSem, &handleVar); + + while (--stackSize >= 0) + { + strcat(path, nodeStack[stackSize]->name); + if (stackSize) + strcat(path, "/"); + } + + return path; +} + +void btMakeHandleFromNode(bt_node *node, bt_fdesc *fdesc) +{ + if (node && fdesc) + fdesc->vnid = node->vnid; +} + +bt_node *btFindNode(bt_node *parent, char *fileName) +{ + bt_node *node; + + btLock(handleSem, &handleVar); + + node = rootNode; + while (node) + { + if (node->parent == parent) + if (strcmp(node->name, fileName) == 0) + break; + + node = node->next; + } + + btUnlock(handleSem, &handleVar); + return node; +} + +char *btGetSharePath(char *shareName) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (stricmp(fileShares[i].name, shareName) == 0) + return fileShares[i].path; + + return NULL; +} + +int btGetShareId(char *shareName) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (stricmp(fileShares[i].name, shareName) == 0) + return i; + + return -1; +} + +// btGetRootPath() +// +void btGetRootPath(vnode_id vnid, char *path) +{ + bt_node *curNode; + + btLock(handleSem, &handleVar); + + curNode = btGetNodeFromVnid(vnid); + while (curNode && curNode->parent) + curNode = curNode->parent; + + if (curNode) + strcpy(path, curNode->name); + else + path[0] = 0; + + btUnlock(handleSem, &handleVar); +} + +void btLock(sem_id semaphore, int32 *atomic) +{ + int32 previous = atomic_add(atomic, 1); + if (previous >= 1) + while (acquire_sem(semaphore) == B_INTERRUPTED); +} + +void btUnlock(sem_id semaphore, int32 *atomic) +{ + int32 previous = atomic_add(atomic, -1); + if (previous > 1) + release_sem(semaphore); +} + +//////////////////////////////////////////////////////////////////// +/* +void btNotifyListeners(char *shareName) +{ + struct sockaddr_in toAddr, fromAddr; + int i; + + for (i = 0; i < BT_MAX_THREADS; i++) + if (stricmp(sessions[i].share, shareName) == 0) + { + memset(&toAddr, 0, sizeof(toAddr)); + toAddr.sin_port = htons(BT_NODE_MONITOR_PORT); + toAddr.sin_family = AF_INET; + toAddr.sin_addr.s_addr = sessions[i].s_addr; + + sendto(sock, packet, sizeof(packet), 0, &fromAddr, sizeof(fromAddr)); + } +} +*/ +//////////////////////////////////////////////////////////////////// + +int btMount(char *shareName, btFileHandle *fhandle) +{ + struct stat st; + bt_fdesc *fdesc; + char *path; + + path = btGetSharePath(shareName); + if (!path) + return ENOENT; + + if (stat(path, &st) != 0) + return ENOENT; + + if (!S_ISDIR(st.st_mode)) + return EACCES; + + fdesc = (bt_fdesc *) fhandle; + fdesc->vnid = st.st_ino; + fdesc->shareId = btGetShareId(shareName); + + btAddHandle(NULL, fdesc, path); + return B_OK; +} + +int btGetFSInfo(fs_info *fsInfo) +{ + dev_t device = dev_for_path(rootNode->name); + if (device < 0) + return device; + + if (fs_stat_dev(device, fsInfo) != 0) + return errno; + + return B_OK; +} + +int btLookup(char *pathBuf, bt_fdesc *ddesc, char *fileName, bt_fdesc *fdesc) +{ + bt_node *dnode, *fnode; + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + + fdesc->vnid = 0; + + btLock(handleSem, &handleVar); + dnode = btGetNodeFromVnid(ddesc->vnid); + btUnlock(handleSem, &handleVar); + + if (!dnode) + return EACCES; + + // Search all nodes for one with the given parent vnid and file + // name. If one is found, we can simply use that node to fill in + // the new handle. + fnode = btFindNode(dnode, fileName); + if (fnode) + { +// btMakeHandleFromNode(fnode, fdesc); + fdesc->vnid = fnode->vnid; + + folder = btGetLocalFileName(pathBuf, fdesc); + if (folder) + if (stat(folder, &st) != 0) + { + btRemoveHandle(fdesc); + fdesc->vnid = 0; + return ENOENT; + } + } + else + { + folder = btGetLocalFileName(pathBuf, ddesc); + if (folder) + { + sprintf(path, "%s/%s", folder, fileName); + if (stat(path, &st) != 0) + return ENOENT; + + fdesc->vnid = st.st_ino; + btAddHandle(ddesc, fdesc, fileName); + } + } + + return B_OK; +} + +int btStat(char *pathBuf, bt_fdesc *fdesc, struct stat *st) +{ + char *fileName; + int error; + + fileName = btGetLocalFileName(pathBuf, fdesc); + if (fileName) + { + error = stat(fileName, st); + return (error != 0 ? ENOENT : B_OK); + } + + return ENOENT; +} + +int btReadDir(char *pathBuf, bt_fdesc *ddesc, DIR **dir, bt_fdesc *fdesc, char *filename, struct stat *st) +{ + struct dirent *dirInfo; + char *folder, path[B_PATH_NAME_LENGTH]; + + if (!ddesc || !fdesc || !filename) + return EINVAL; + + if (!*dir) + { + folder = btGetLocalFileName(pathBuf, ddesc); + if (folder) + *dir = opendir(folder); + } + + if (*dir) + if ((dirInfo = readdir(*dir)) != NULL) + { + folder = btGetLocalFileName(pathBuf, ddesc); + if (folder) + { + sprintf(path, "%s/%s", folder, dirInfo->d_name); + if (stat(path, st) != 0) + return ENOENT; + + strcpy(filename, dirInfo->d_name); + fdesc->vnid = st->st_ino; + btAddHandle(ddesc, fdesc, filename); + return B_OK; + } + } + else + { + closedir(*dir); + return ENOENT; + } + + return EINVAL; +} + +int32 btRead(char *pathBuf, bt_fdesc *fdesc, off_t pos, int32 len, char *buffer) +{ + char *path; + + path = btGetLocalFileName(pathBuf, fdesc); + if (path) + { + FILE *fp = fopen(path, "rb"); + if (fp) + { + fseek(fp, pos, SEEK_SET); + len = fread(buffer, 1, len, fp); + fclose(fp); + + buffer[len] = 0; + return len; + } + } + + return 0; +} + +int32 btWrite(char *pathBuf, bt_fdesc *fdesc, off_t pos, int32 len, char *buffer) +{ + char *path; + int32 bytes; + + path = btGetLocalFileName(pathBuf, fdesc); + if (path) + { + int file; + file = open(path, O_WRONLY | O_CREAT); + if (file >= 0) + { + lseek(file, pos, SEEK_SET); + bytes = write(file, buffer, len); + close(file); + return bytes; + } + } + + return 0; +} + +int btCreate(char *pathBuf, bt_fdesc *ddesc, char *name, int omode, int perms, bt_fdesc *fdesc) +{ + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + int fh; + + folder = btGetLocalFileName(pathBuf, ddesc); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + fh = open(path, O_RDWR | O_CREAT | omode); + if (fh == -1) + return errno; + else + { + close(fh); + chmod(path, perms); + if (stat(path, &st) == 0) + { + fdesc->vnid = st.st_ino; + btAddHandle(ddesc, fdesc, name); + } + else + return EACCES; + } + } + + return B_OK; +} + +int btTruncate(char *pathBuf, bt_fdesc *fdesc, int64 len) +{ + char *path; + int error; + + path = btGetLocalFileName(pathBuf, fdesc); + if (path) + { + error = truncate(path, len); + if (error == -1) + error = errno; + + return error; + } + + return EACCES; +} + +// btCreateDir() +// +int btCreateDir(char *pathBuf, bt_fdesc *ddesc, char *name, int perms, bt_fdesc *fdesc, struct stat *st) +{ + char path[B_PATH_NAME_LENGTH], *folder; + + folder = btGetLocalFileName(pathBuf, ddesc); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + if (mkdir(path, perms) == -1) + return errno; + + if (stat(path, st) != 0) + return errno; + + fdesc->vnid = st->st_ino; + btAddHandle(ddesc, fdesc, name); + return B_OK; + } + + return ENOENT; +} + +// btDeleteDir() +// +int btDeleteDir(char *pathBuf, bt_fdesc *ddesc, char *name) +{ + bt_fdesc fdesc; + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + + folder = btGetLocalFileName(pathBuf, ddesc); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + if (stat(path, &st) != 0) + return errno; + + if (rmdir(path) == -1) + return errno; + + fdesc.vnid = st.st_ino; + btPurgeNodes(&fdesc); + return B_OK; + } + + return ENOENT; +} + +// btRename() +// +int btRename(char *pathBuf, bt_fdesc *oldfdesc, char *oldName, bt_fdesc *newfdesc, char *newName) +{ + bt_fdesc fdesc; + struct stat st; + char oldPath[B_PATH_NAME_LENGTH], newPath[B_PATH_NAME_LENGTH], *oldFolder, *newFolder; + + oldFolder = btGetLocalFileName(pathBuf, oldfdesc); + if (oldFolder) + { + sprintf(oldPath, "%s/%s", oldFolder, oldName); + + newFolder = btGetLocalFileName(pathBuf, newfdesc); + if (newFolder) + { + sprintf(newPath, "%s/%s", newFolder, newName); + + if (stat(oldPath, &st) != 0) + return errno; + + fdesc.vnid = st.st_ino; + btPurgeNodes(&fdesc); + + if (rename(oldPath, newPath) == -1) + return errno; + + return B_OK; + } + } + + return ENOENT; +} + +// btUnlink() +// +int btUnlink(char *pathBuf, bt_fdesc *ddesc, char *name) +{ + bt_fdesc fdesc; + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + int error; + + folder = btGetLocalFileName(pathBuf, ddesc); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + + // Obtain the inode (vnid) of the specified file through stat(). + if (stat(path, &st) != 0) + return errno; + + // Construct a dummy file descriptor and cause it to be removed from + // the list. + fdesc.vnid = st.st_ino; + btRemoveHandle(&fdesc); + + error = unlink(path); + return (error == -1 ? errno : B_OK); + } + + return EACCES; +} + +int btReadLink(char *pathBuf, bt_fdesc *fdesc, char *buffer, int length) +{ + char *path; + int error; + + path = btGetLocalFileName(pathBuf, fdesc); + if (path) + { + error = readlink(path, buffer, length); + if (error == -1) + return errno; + + return B_OK; + } + + return ENOENT; +} + +int btSymLink(char *pathBuf, bt_fdesc *fdesc, char *name, char *dest) +{ + char path[B_PATH_NAME_LENGTH], *folder; + + folder = btGetLocalFileName(pathBuf, fdesc); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + if (symlink(dest, path) == -1) + return errno; + + return B_OK; + } + + return ENOENT; +} + +int btWStat(char *pathBuf, bt_fdesc *fdesc, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime) +{ + struct utimbuf ftimes; + struct stat st; + char *path; + + path = btGetLocalFileName(pathBuf, fdesc); + if (path) + { + if (mask & WSTAT_MODE) + chmod(path, mode); + + if (mask & WSTAT_UID) + chown(path, uid, -1); + + if (mask & WSTAT_GID) + chown(path, -1, gid); + + if (mask & WSTAT_SIZE) + truncate(path, size); + + if (stat(path, &st) == 0) + if (mask & WSTAT_ATIME || mask & WSTAT_MTIME) + { + ftimes.actime = mask & WSTAT_ATIME ? atime : st.st_atime; + ftimes.modtime = mask & WSTAT_MTIME ? mtime : st.st_mtime; + utime(path, &ftimes); + } + + return B_OK; + } + + return ENOENT; +} + +int btReadAttrib(char *pathBuf, bt_fdesc *fdesc, char *name, int32 dataType, void *buffer, int32 pos, int32 len) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, fdesc); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int bytes = (int) fs_read_attr(file, name, dataType, pos, buffer, len); + close(file); + + if (dataType == B_STRING_TYPE && bytes < len && bytes >= 0) + ((char *) buffer)[bytes] = 0; + + return bytes; + } + } + + return ENOENT; +} + +int btWriteAttrib(char *pathBuf, bt_fdesc *fdesc, char *name, int32 dataType, void *buffer, int32 pos, int32 len) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, fdesc); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int bytes = (int) fs_write_attr(file, name, dataType, pos, buffer, len); + close(file); + return bytes; + } + } + + return ENOENT; +} + +int btReadAttribDir(char *pathBuf, bt_fdesc *fdesc, DIR **dir, char *attrName) +{ + dirent_t *entry; + char *path; + + if (!fdesc || !attrName) + return EINVAL; + + if (!*dir) + { + path = btGetLocalFileName(pathBuf, fdesc); + if (path) + *dir = fs_open_attr_dir(path); + } + + if (*dir) + do + { + entry = fs_read_attr_dir(*dir); + if (entry) + { + if (strncmp(entry->d_name, "_trk/", 5) == 0) + continue; + + strcpy(attrName, entry->d_name); + return B_OK; + } + } while (entry); + + if (*dir) + fs_close_attr_dir(*dir); + + return ENOENT; +} + +int btRemoveAttrib(char *pathBuf, bt_fdesc *fdesc, char *name) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, fdesc); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int error = fs_remove_attr(file, name); + if (error == -1) + error = errno; + + close(file); + return error; + } + } + + return ENOENT; +} + +int btStatAttrib(char *pathBuf, bt_fdesc *fdesc, char *name, struct attr_info *info) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, fdesc); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int error = fs_stat_attr(file, name, info); + if (error == -1) + error = errno; + + close(file); + return error; + } + } + + return ENOENT; +} + +int btReadIndexDir(DIR **dir, char *indexName) +{ + struct dirent *dirInfo; + + if (!*dir) + { + dev_t device = dev_for_path(rootNode->name); + if (device < 0) + return device; + + *dir = fs_open_index_dir(device); + } + + if (*dir) + if ((dirInfo = fs_read_index_dir(*dir)) != NULL) + { + strcpy(indexName, dirInfo->d_name); + return B_OK; + } + else + { + fs_close_index_dir(*dir); + *dir = NULL; + return ENOENT; + } + + return ENOENT; +} + +int btCreateIndex(char *name, int type, int flags) +{ + dev_t device = dev_for_path(rootNode->name); + if (device < 0) + return device; + + if (fs_create_index(device, name, type, flags) == -1) + return errno; + + return B_OK; +} + +int btRemoveIndex(char *name) +{ + dev_t device = dev_for_path(rootNode->name); + if (device < 0) + return device; + + if (fs_remove_index(device, name) == -1) + return errno; + + return B_OK; +} + +int btStatIndex(char *name, struct index_info *info) +{ + dev_t device = dev_for_path(rootNode->name); + if (device < 0) + return device; + + if (fs_stat_index(device, name, info) == -1) + return errno; + + return B_OK; +} + +int btReadQuery(DIR **dir, char *query, char *fileName, int64 *inode) +{ + struct dirent *dirInfo; + + if (!*dir) + { + dev_t device = dev_for_path(rootNode->name); + if (device < 0) + return device; + + printf("Querying: %s\n", query); + *dir = fs_open_query(device, query, 0); + } + + if (*dir) + if ((dirInfo = fs_read_query(*dir)) != NULL) + { + *inode = dirInfo->d_ino; + strcpy(fileName, dirInfo->d_name); + printf("Query matched %s\n", fileName); + return B_OK; + } + else + { + fs_close_query(*dir); + *dir = NULL; + return ENOENT; + } + + return ENOENT; +} + +//////////////////////////////////////////////////////////////////// + +void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + btFileHandle rootNode; + int client, error; + + client = session->socket; + if (argc == 1) + { + if (argv[0].type == B_STRING_TYPE) + { + char *shareName = argv[0].data; + error = btMount(shareName, &rootNode); + if (error == B_OK) + { + strcpy(session->share, shareName); + + btRPCCreateAck(&packet, xid, error, BT_FILE_HANDLE_SIZE); + btRPCPutHandle(&packet, &rootNode); + } + else + btRPCCreateAck(&packet, xid, error, 0); + + btRPCSendAck(client, &packet); + return; + } + } + +// sendErrorToClient(client, EINVAL); +} + +void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + { + if (argv[0].type == B_STRING_TYPE) + { + fs_info info; + + error = btGetFSInfo(&info); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, error, 12); + btRPCPutInt32(&packet, info.block_size); + btRPCPutInt32(&packet, info.total_blocks); + btRPCPutInt32(&packet, info.free_blocks); + } + else + btRPCCreateAck(&packet, xid, error, 0); + + btRPCSendAck(client, &packet); + return; + } + } + +// sendErrorToClient(client, EINVAL); +} + +void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + struct stat st; + int client, error; + + client = session->socket; + if (argc == 2) + { + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE) + { + bt_fdesc fdesc; + error = btLookup(session->pathBuffer, (bt_fdesc *) argv[0].data, argv[1].data, &fdesc); + if (error == B_OK) + error = btStat(session->pathBuffer, &fdesc, &st); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK, BT_FILE_HANDLE_SIZE + 52); + btRPCPutHandle(&packet, (btFileHandle *) &fdesc); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error, 0); + + btRPCSendAck(client, &packet); + return; + } + } + +// sendErrorToClient(client, EINVAL); +} + +void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + struct stat st; + int client, error; + + client = session->socket; + if (argc == 2) + { + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE) + { + bt_fdesc fdesc; + DIR *dir; + char filename[B_PATH_NAME_LENGTH]; + int entries = 0; + + dir = (DIR *)(*((int32 *) argv[1].data)); + error = btReadDir(session->pathBuffer, (bt_fdesc *) argv[0].data, &dir, &fdesc, filename, &st); + + if (error != B_OK) + { + btRPCCreateAck(&packet, xid, error, 0); + btRPCSendAck(client, &packet); + return; + } + + btRPCCreateAck(&packet, xid, B_OK, 0); + while (error == B_OK) + { + btRPCPutInt64(&packet, fdesc.vnid); + btRPCPutString(&packet, filename, strlen(filename)); + btRPCPutInt32(&packet, (int32) dir); + btRPCPutHandle(&packet, (btFileHandle *) &fdesc); + btRPCPutStat(&packet, &st); + + if (++entries >= 32) + break; + + error = btReadDir(session->pathBuffer, (bt_fdesc *) argv[0].data, &dir, &fdesc, filename, &st); + btRPCPutInt32(&packet, error); + } + + // If we exhausted the list of directory entries without filling + // the buffer, add an error message that will prevent the client + // from requesting further entries. + if (entries < 32) + btRPCPutInt32(&packet, ENOENT); + + btRPCSendAck(client, &packet); + return; + } + } + +// sendErrorToClient(client, EINVAL); +} + +void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + if (argv[0].type == B_STRING_TYPE) + { + struct stat info; + + error = btStat(session->pathBuffer, (bt_fdesc *) argv[0].data, &info); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, error, 52); + btRPCPutStat(&packet, &info); + } + else + btRPCCreateAck(&packet, xid, error, 0); + + btRPCSendAck(client, &packet); + return; + } + +// sendErrorToClient(client, EINVAL); +} + +void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + if (argc == 3) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_INT32_TYPE && argv[2].type == B_INT32_TYPE) + { + off_t pos = *((off_t *) argv[1].data); + int32 len = *((int32 *) argv[2].data); + int32 bytes = 0; + + session->ioBuffer[len] = 0; + bytes = btRead(session->pathBuffer, (bt_fdesc *) argv[0].data, pos, len, session->ioBuffer); + + btRPCCreateAck(&packet, xid, B_OK, bytes + 4); + btRPCPutString(&packet, session->ioBuffer, bytes); + btRPCSendAck(client, &packet); + return; + } +} + +void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + if (argc == 4) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_INT64_TYPE && argv[2].type == B_INT32_TYPE && argv[3].type == B_STRING_TYPE) + { + off_t pos = *((off_t *) argv[1].data); + int32 len = *((int32 *) argv[2].data); + int32 bytes; + + bytes = btWrite(session->pathBuffer, (bt_fdesc *) argv[0].data, pos, len, argv[3].data); + if (bytes == len) + { + btRPCCreateAck(&packet, xid, B_OK, 4); + btRPCPutInt32(&packet, bytes); + } + else + btRPCCreateAck(&packet, xid, EACCES, 0); + + btRPCSendAck(client, &packet); + return; + } +} + +void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + struct stat st; + int client, error; + + client = session->socket; + if (argc == 4) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_INT32_TYPE && argv[3].type == B_INT32_TYPE) + { + bt_fdesc fdesc; + int omode = *((int *) argv[2].data); + int perms = *((int *) argv[3].data); + + error = btCreate(session->pathBuffer, (bt_fdesc *) argv[0].data, argv[1].data, omode, perms, &fdesc); + if (error == B_OK) + error = btStat(session->pathBuffer, &fdesc, &st); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK, 0); + btRPCPutHandle(&packet, (btFileHandle *) &fdesc); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error, 0); + + btRPCSendAck(client, &packet); + return; + } +} + +void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_INT64_TYPE) + { + error = btTruncate(session->pathBuffer, (bt_fdesc *) argv[0].data, *((int64 *) argv[1].data)); + btRPCCreateAck(&packet, xid, error, 0); + btRPCSendAck(client, &packet); + return; + } +} + +void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE) + { + error = btUnlink(session->pathBuffer, (bt_fdesc *) argv[0].data, argv[1].data); + btRPCCreateAck(&packet, xid, error, 0); + btRPCSendAck(client, &packet); + return; + } +} + +void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 4) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_STRING_TYPE && argv[3].type == B_STRING_TYPE) + { + error = btRename(session->pathBuffer, (bt_fdesc *) argv[0].data, argv[1].data, (bt_fdesc *) argv[2].data, argv[3].data); + btRPCCreateAck(&packet, xid, error, 0); + btRPCSendAck(client, &packet); + return; + } +} + +void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 3) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_INT32_TYPE) + { + bt_fdesc fdesc; + struct stat st; + + error = btCreateDir(session->pathBuffer, (bt_fdesc *) argv[0].data, argv[1].data, *((int *) argv[2].data), &fdesc, &st); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK, BT_FILE_HANDLE_SIZE + 52); + btRPCPutHandle(&packet, (btFileHandle *) &fdesc); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error, 0); + + btRPCSendAck(client, &packet); + return; + } +} + +void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE) + { + error = btDeleteDir(session->pathBuffer, (bt_fdesc *) argv[0].data, argv[1].data); + btRPCCreateAck(&packet, xid, error, 0); + btRPCSendAck(client, &packet); + return; + } +} + +void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + if (argv[0].type == B_STRING_TYPE) + { + char path[B_PATH_NAME_LENGTH]; + error = btReadLink(session->pathBuffer, (bt_fdesc *) argv[0].data, path, B_PATH_NAME_LENGTH); + if (error == B_OK) + { + int length = strlen(path); + btRPCCreateAck(&packet, xid, B_OK, length); + btRPCPutString(&packet, path, length); + } + else + btRPCCreateAck(&packet, xid, error, 0); + + btRPCSendAck(client, &packet); + } +} + +void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 3) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_STRING_TYPE) + { + error = btSymLink(session->pathBuffer, (bt_fdesc *) argv[0].data, argv[1].data, argv[2].data); + btRPCCreateAck(&packet, xid, error, 0); + btRPCSendAck(client, &packet); + } +} + +void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 8) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_INT32_TYPE && argv[2].type == B_INT32_TYPE && + argv[3].type == B_INT32_TYPE && argv[4].type == B_INT32_TYPE && argv[5].type == B_INT32_TYPE && + argv[6].type == B_INT32_TYPE && argv[7].type == B_INT32_TYPE) + { + int32 mask = *((int32 *) argv[1].data); + int32 mode = *((int32 *) argv[2].data); + int32 uid = *((int32 *) argv[3].data); + int32 gid = *((int32 *) argv[4].data); + int64 size = (int64) *((int32 *) argv[5].data); + int32 atime = *((int32 *) argv[6].data); + int32 mtime = *((int32 *) argv[7].data); + + error = btWStat(session->pathBuffer, (bt_fdesc *) argv[0].data, mask, mode, uid, gid, size, atime, mtime); + btRPCCreateAck(&packet, xid, error, 0); + btRPCSendAck(client, &packet); + } +} + +void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, bytesRead; + + client = session->socket; + if (argc == 5) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_INT32_TYPE && + argv[3].type == B_INT32_TYPE && argv[4].type == B_INT32_TYPE) + { + char *buffer; + int32 type = *((int32 *) argv[2].data); + int32 pos = *((int32 *) argv[3].data); + int32 len = *((int32 *) argv[4].data); + + if (len <= BT_MAX_ATTR_BUFFER) + buffer = session->attrBuffer; + else + buffer = (char *) malloc(len + 1); + + if (buffer) + { + bytesRead = btReadAttrib(session->pathBuffer, (bt_fdesc *) argv[0].data, argv[1].data, type, buffer, pos, len); + if (bytesRead >= 0) + { + btRPCCreateAck(&packet, xid, B_OK, bytesRead + 8); + btRPCPutInt32(&packet, (int32) bytesRead); + if (bytesRead > 0) + btRPCPutString(&packet, buffer, bytesRead); + } + else + btRPCCreateAck(&packet, xid, B_ENTRY_NOT_FOUND, 0); + + if (len > BT_MAX_ATTR_BUFFER) + free(buffer); + } + else + btRPCCreateAck(&packet, xid, ENOMEM, 0); + + btRPCSendAck(client, &packet); + return; + } +} + +void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, bytesWritten; + + client = session->socket; + if (argc == 6) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_INT32_TYPE && + argv[3].type == B_STRING_TYPE && argv[4].type == B_INT32_TYPE && argv[5].type == B_INT32_TYPE) + { + int32 type = *((int32 *) argv[2].data); + int32 pos = *((int32 *) argv[4].data); + int32 len = *((int32 *) argv[5].data); + + bytesWritten = btWriteAttrib(session->pathBuffer, (bt_fdesc *) argv[0].data, argv[1].data, type, argv[3].data, pos, len); + if (bytesWritten >= 0) + { + btRPCCreateAck(&packet, xid, B_OK, 4); + btRPCPutInt32(&packet, (int32) bytesWritten); + } + else + btRPCCreateAck(&packet, xid, B_ENTRY_NOT_FOUND, 0); + + btRPCSendAck(client, &packet); + return; + } +} + +void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + { + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE) + { + DIR *dir; + char attrName[100]; + int entries = 0; + + dir = (DIR *)(*((int32 *) argv[1].data)); + error = btReadAttribDir(session->pathBuffer, (bt_fdesc *) argv[0].data, &dir, attrName); + + if (error != B_OK) + { + btRPCCreateAck(&packet, xid, error, 0); + btRPCSendAck(client, &packet); + return; + } + + btRPCCreateAck(&packet, xid, B_OK, 0); + while (error == B_OK) + { + btRPCPutString(&packet, attrName, strlen(attrName)); + btRPCPutInt32(&packet, (int32) dir); + + if (++entries >= 32) + break; + + error = btReadAttribDir(session->pathBuffer, (bt_fdesc *) argv[0].data, &dir, attrName); + btRPCPutInt32(&packet, error); + } + + if (entries < 32) + btRPCPutInt32(&packet, ENOENT); + + btRPCSendAck(client, &packet); + return; + } + } + +// sendErrorToClient(client, EINVAL); +} + +void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE) + { + error = btRemoveAttrib(session->pathBuffer, (bt_fdesc *) argv[0].data, argv[1].data); + btRPCCreateAck(&packet, xid, error, 0); + btRPCSendAck(client, &packet); + return; + } +} + +void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE) + { + struct attr_info info; + + error = btStatAttrib(session->pathBuffer, (bt_fdesc *) argv[0].data, argv[1].data, &info); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK, 12); + btRPCPutInt32(&packet, info.type); + btRPCPutInt64(&packet, info.size); + } + else + btRPCCreateAck(&packet, xid, error, 0); + + btRPCSendAck(client, &packet); + return; + } +} + +void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + if (argv[0].type == B_STRING_TYPE) + { + DIR *dir; + char indexName[100]; + + dir = (DIR *)(*((int32 *) argv[0].data)); + + error = btReadIndexDir(&dir, indexName); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK, strlen(indexName) + 8); + btRPCPutString(&packet, indexName, strlen(indexName)); + btRPCPutInt32(&packet, (int32) dir); + } + else + btRPCCreateAck(&packet, xid, error, 0); + + btRPCSendAck(client, &packet); + return; + } +} + +void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 3) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_INT32_TYPE && argv[2].type == B_INT32_TYPE) + { + int type = *((int32 *) argv[1].data); + int flags = *((int32 *) argv[2].data); + + error = btCreateIndex(argv[0].data, type, flags); + btRPCCreateAck(&packet, xid, error, 0); + btRPCSendAck(client, &packet); + return; + } +} + +void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + if (argv[0].type == B_STRING_TYPE) + { + error = btRemoveIndex(argv[0].data); + btRPCCreateAck(&packet, xid, error, 0); + btRPCSendAck(client, &packet); + return; + } +} + +void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + if (argv[0].type == B_STRING_TYPE) + { + struct index_info info; + + error = btStatIndex(argv[0].data, &info); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK, 28); + btRPCPutInt32(&packet, info.type); + btRPCPutInt64(&packet, info.size); + btRPCPutInt32(&packet, info.modification_time); + btRPCPutInt32(&packet, info.creation_time); + btRPCPutInt32(&packet, info.uid); + btRPCPutInt32(&packet, info.gid); + } + else + btRPCCreateAck(&packet, xid, error, 0); + + btRPCSendAck(client, &packet); + return; + } +} + +void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE) + { + DIR *dir; + char fileName[B_PATH_NAME_LENGTH]; + int64 inode; + + dir = (DIR *)(*((int32 *) argv[0].data)); + + error = btReadQuery(&dir, argv[1].data, fileName, &inode); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK, strlen(fileName) + 16); + btRPCPutInt64(&packet, inode); + btRPCPutString(&packet, fileName, strlen(fileName)); + btRPCPutInt32(&packet, (int32) dir); + } + else + btRPCCreateAck(&packet, xid, error, 0); + + btRPCSendAck(client, &packet); + return; + } +} + +// netbtQuit() +// +void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + if (argc == 0) + { + btRPCCreateAck(&packet, xid, B_OK, 0); + btRPCSendAck(client, &packet); + } +} + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/betalk.h new file mode 100644 index 0000000000..0575c5e0b6 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/betalk.h @@ -0,0 +1,147 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 8000 +#define BT_QUERYHOST_PORT 8001 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_QUIT 255 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 16384 +#define BT_RPC_MIN_PACKET_SIZE 64 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define MAX_COMMAND_ARGS 10 +#define MAX_ENTRY_VERSIONS 10 + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +#define BT_COOKIE_SIZE 4 +#define BT_QUERY_COOKIE_SIZE 4 +#define BT_FILE_HANDLE_SIZE 32 + +typedef struct btFileHandle +{ + char opaque[BT_FILE_HANDLE_SIZE]; +} btFileHandle; + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +// RPC Operations +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetHandle(bt_inPacket *packet, btFileHandle *fhandle); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutHandle(bt_outPacket *packet, btFileHandle *fhandle); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +bt_rpccall * btRPCInvoke(int session, bt_outPacket *packet); +bt_outPacket *btRPCCreateAck(unsigned int xid, int error, int length); +void btRPCSendAck(int client, bt_outPacket *packet); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/btClient.c b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/btClient.c new file mode 100644 index 0000000000..c7ab7615f1 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/btClient.c @@ -0,0 +1,1628 @@ +// LDAPAdd.cpp : Defines the entry point for the console application. +// + +#include "betalk.h" + +#include "netdb.h" +#include "nfs_add_on.h" +#include "ksocket.h" + +#define BT_RPC_THREAD_NAME "BeServed Client RPC" +#define BT_MAX_TOTAL_RETRIES 3 +#define BT_RETRIES_BEFORE_RESTART 1 + +typedef struct mimeCache +{ + vnode_id vnid; + time_t time; + char mimeType[256]; + struct mimeCache *prev, *next; +} bt_mimeCacheNode; + + +int btConnect(unsigned int serverIP, int port); +void btDisconnect(int session); +void btReconnect(); +int32 btRPCReceive(void *data); +void btRPCInit(fs_nspace *ns); +void btRPCClose(); + +void btRPCRecordCall(bt_rpccall *call); +void btRPCRemoveCall(bt_rpccall *call); +void btRPCFreeCall(bt_rpccall *call); +void btCreateInPacket(bt_rpccall *call, char *buffer, unsigned int length); +void btDestroyInPacket(bt_inPacket *packet); + +void btAddToMimeCache(vnode_id vnid, char *mimeType, char *pktBuffer); +bt_mimeCacheNode *btRemoveFromMimeCache(bt_mimeCacheNode *deadNode); +char *btGetMimeType(vnode_id vnid); + +int btMount(int session, char *shareName, vnode_id *vnid); +int btLookup(int session, vnode_id dir_vnid, char *file, vnode_id *file_vnid, struct stat *st); +int btStat(int session, vnode_id vnid, struct stat *st); +int btGetFSInfo(int session, btFileHandle *root, bt_fsinfo *fsinfo); +int btReadDir(int session, btFileHandle *dhandle, vnode_id *vnid, char **filename, btCookie *cookie, struct stat *st); +size_t btRead(int session, btFileHandle *fhandle, off_t pos, size_t len, char *buf); +int btCreate(int session, btFileHandle *dhandle, char *name, vnode_id *file_vnid, int omode, int perms, struct stat *st); +int btTruncate(int session, btFileHandle *fhandle, int64 len); +int btUnlink(int session, btFileHandle *dhandle, char *name); +int btCreateDir(int session, btFileHandle *dhandle, char *name, int perms, vnode_id *file_vnid, struct stat *st); +int btRename(int session, btFileHandle *oldDHandle, char *oldName, btFileHandle *newDHandle, char *newName); +int btDeleteDir(int session, btFileHandle *dhandle, char *name); +int btReadLink(int session, btFileHandle *fhandle, char *buf, size_t *bufsize); +int btSymLink(int session, btFileHandle *dhandle, char *name, char *path); +int btReadAttrib(int session, btFileHandle *fhandle, char *name, int type, void *buffer, size_t len, off_t pos); +int btWriteAttrib(int session, btFileHandle *fhandle, char *name, int type, void *buffer, size_t len, off_t pos); +int btReadAttribDir(int session, btFileHandle *fhandle, char **attrName, btCookie *cookie); +int btRemoveAttrib(int session, btFileHandle *fhandle, char *name); +int btStatAttrib(int session, btFileHandle *fhandle, char *name, struct attr_info *info); +int btReadIndexDir(int session, char **indexName, int bufLength, btCookie *cookie); +int btCreateIndex(int session, char *name, int type, int flags); +int btRemoveIndex(int session, char *name); +int btStatIndex(int session, char *name, struct index_info *buf); +int btReadQuery(int session, char **fileName, int64 *inode, btQueryCookie *cookie); + + +bt_rpccall *rootCall = NULL; +bt_mimeCacheNode *mimeRoot = NULL; + +thread_id rpcThread = 0; +sem_id callSem; +sem_id connectSem; +sem_id mimeSem; + +fs_nspace *lastFS; + +unsigned int lastServerIP; +int lastPort; + +vint32 fsRefCount = 0; +vint32 nextXID = 1; +int32 quitXID = 0; + + +void btRPCInit(fs_nspace *ns) +{ + lastFS = ns; + + callSem = create_sem(1, "rpcCall"); + set_sem_owner(callSem, B_SYSTEM_TEAM); + + connectSem = create_sem(1, "rpcConnection"); + set_sem_owner(connectSem, B_SYSTEM_TEAM); + + // Find the RPC response recipient thread. If none can be found, create one. + // Otherwise, set the thread ID back to zero so that when we shut down, we + // won't try to kill a thread we didn't create. +// if (fsRefCount == 0) +// { + rpcThread = spawn_kernel_thread(btRPCReceive, BT_RPC_THREAD_NAME, B_NORMAL_PRIORITY, ns); + resume_thread(rpcThread); +// } +// else +// rpcThread = 0; +} + +void btRPCClose() +{ +// if (fsRefCount == 0) + if (rpcThread > 0) + { + status_t exitVal; + wait_for_thread(rpcThread, &exitVal); + } + + // Close the socket used for all file system RPC communications, + // now that we know the RPC recipient thread is dead. + kclosesocket(lastFS->s); + + delete_sem(connectSem); + delete_sem(callSem); + +// if (fsRefCount == 0) + lastFS = NULL; +} + +int32 btRPCReceive(void *data) +{ + fs_nspace *ns = (fs_nspace *) data; + bt_rpccall *call; + char signature[20], *buffer; + int32 xid, nsid, length, sigLen, bytesRead; + int sock = ns->s; + + while (true) + { + sigLen = strlen(BT_RPC_SIGNATURE); + memset(signature, 0, sigLen); + if (krecv(sock, signature, sigLen, 0) == 0) + continue; + + signature[sigLen] = 0; + if (strcmp(signature, BT_RPC_SIGNATURE)) + continue; + +// krecv(sock, &nsid, sizeof(nsid), 0); + krecv(sock, &xid, sizeof(int32), 0); + krecv(sock, &length, sizeof(int32), 0); + + if (length == 0 || length >= BT_RPC_MAX_PACKET_SIZE) + continue; + + buffer = (char *) malloc(length + 1); + if (!buffer) + continue; + + bytesRead = 0; + do + { + bytesRead += krecv(sock, buffer + bytesRead, length - bytesRead, 0); + } while (bytesRead < length); + + buffer[length] = 0; + + while (acquire_sem(callSem) == B_INTERRUPTED); + + call = rootCall; + while (call) + { +// if (call->nsid == nsid) + if (call->xid == xid) + { + btCreateInPacket(call, buffer, length); + release_sem(call->sem); + break; + } + + call = call->next; + } + + release_sem(callSem); + + // The originating RPC call was not found. This is probably not a very + // good sign. + if (!call) + free(buffer); + + // If a valid quit XID has been defined, and it's equal to the current + // XID, quit. + if (!fsRefCount && quitXID) + if (quitXID == xid) + break; + } +} + +void btCreateInPacket(bt_rpccall *call, char *buffer, unsigned int length) +{ + bt_inPacket *packet; + + packet = (bt_inPacket *) malloc(sizeof(bt_inPacket)); + if (!packet) + return; + + packet->buffer = buffer; + packet->length = length; + packet->offset = 0; + + call->inPacket = packet; +} + +void btDestroyInPacket(bt_inPacket *packet) +{ + if (packet) + { + if (packet->buffer) + free(packet->buffer); + + free(packet); + } +} + +void btRPCRecordCall(bt_rpccall *call) +{ + bt_rpccall *curCall, *lastCall; + + while (acquire_sem(callSem) == B_INTERRUPTED); + + curCall = lastCall = rootCall; + while (curCall) + { + lastCall = curCall; + curCall = curCall->next; + } + + call->next = NULL; + call->prev = lastCall; + + if (lastCall == NULL) + rootCall = call; + else + lastCall->next = call; + + release_sem(callSem); +} + +// btRPCRemoveCall() +// +void btRPCRemoveCall(bt_rpccall *call) +{ + if (call) + { + while (acquire_sem(callSem) == B_INTERRUPTED); + + if (call->sem > 0) + delete_sem(call->sem); + + // Make this entry's predecessor point to its successor. + if (call->prev) + call->prev->next = call->next; + + // Make this entry's successor point to its predecessor. + if (call->next) + call->next->prev = call->prev; + + // If an inbound packet was ever received for this RPC call, + // deallocate it now. + call->finished = true; + + release_sem(callSem); + } +} + +// btRPCFreeCall() +// +void btRPCFreeCall(bt_rpccall *call) +{ + if (call) + { +// btDestroyInPacket(call->inPacket); +// free(call); + } +} + +// btConnect() +// +int btConnect(unsigned int serverIP, int port) +{ + struct sockaddr_in serverAddr; + int session, addrLen; + + lastServerIP = serverIP; + lastPort = port; + + // Store the length of the socket addressing structure for accept(). + addrLen = sizeof(struct sockaddr_in); + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(port); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(serverIP); // inet_addr(server); // 16777343; + + // Create a new socket to receive incoming requests. + session = ksocket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (session == INVALID_SOCKET) + return INVALID_SOCKET; + + // Bind that socket to the address constructed above. + if (kconnect(session, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return INVALID_SOCKET; + + atomic_add(&fsRefCount, 1); + return session; +} + +void btDisconnect(int session) +{ + bt_outPacket *packet; + bt_rpccall *call; + + // Note that we decrement the file system reference count before we + // actually send the QUIT command, since the RPC response recipient + // thread will need to exit when the packet is received and potentially + // before we regain control here. The worst case would be that + // transmission of the QUIT command fails, and the recipient thread is + // left running. However, it will either be re-used on the next + // mount or sit idle in a recv() call. + atomic_add(&fsRefCount, -1); + + packet = btRPCPutHeader(BT_CMD_QUIT, 0, 0); + call = btRPCInvoke(session, packet, true); + if (call) + btRPCRemoveCall(call); +} + +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length) +{ + bt_outPacket *packet; + + packet = (bt_outPacket *) malloc(sizeof(bt_outPacket)); + if (!packet) + return NULL; + + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + { + free(packet); + return NULL; + } + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + +// btRPCPutChar(packet, BT_RPC_VERSION_HI); +// btRPCPutChar(packet, BT_RPC_VERSION_LO); + btRPCPutInt32(packet, 7 + (8 * argc) + length); + btRPCPutChar(packet, command); + btRPCPutChar(packet, argc); + + return packet; +} + +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length) +{ + btRPCPutInt32(packet, type); + btRPCPutInt32(packet, length); + btRPCPutBinary(packet, data, length); +} + +bt_rpccall *btRPCInvoke(int session, bt_outPacket *packet, bool lastPkt) +{ + status_t result; + bt_rpccall *call; + int retries; + int32 bytesSent; + + call = (bt_rpccall *) malloc(sizeof(bt_rpccall)); + if (!call) + return NULL; + + retries = 0; + + call->inPacket = NULL; + call->finished = false; + call->xid = atomic_add(&nextXID, 1); + if ((call->sem = create_sem(0, "rpc call")) < B_OK) + { + free(call); + return NULL; + } + + set_sem_owner(call->sem, B_SYSTEM_TEAM); + btRPCRecordCall(call); + +// btRPCPutInt32(packet, call->nsid); + btRPCPutInt32(packet, call->xid); + btRPCPutChar(packet, BT_CMD_TERMINATOR); + + // If this is the last RPC packet that will be transmitted, store + // its XID so the RPC recipient thread will know when to quit. + if (lastPkt) + quitXID = call->xid; + +doSend: + bytesSent = 0; + do + { + int bytes; + bytes = ksend(session, packet->buffer + bytesSent, packet->length - bytesSent, 0); + if (bytes > 0) + bytesSent += bytes; + } while (bytesSent < packet->length); + + do + { + result = acquire_sem_etc(call->sem, 1, B_RELATIVE_TIMEOUT, 5000000); + } + while (result == B_INTERRUPTED); + + if (result == B_TIMED_OUT) + { + retries++; + if (retries > BT_MAX_TOTAL_RETRIES) + { + free(packet->buffer); + free(packet); + btRPCRemoveCall(call); + return NULL; + } + else if (retries > BT_RETRIES_BEFORE_RESTART) + btReconnect(); + + goto doSend; + } + + free(packet->buffer); + free(packet); + return call; +} + +void btReconnect() +{ + static int counter = 0; + int curCount = counter; + + while (acquire_sem(connectSem) == B_INTERRUPTED); + + if (curCount == counter) + { + kclosesocket(lastFS->s); + atomic_add(&fsRefCount, -1); + + lastFS->s = btConnect(lastServerIP, lastPort); + + if (rpcThread > 0) + { + kill_thread(rpcThread); + rpcThread = spawn_kernel_thread(btRPCReceive, BT_RPC_THREAD_NAME, B_NORMAL_PRIORITY, lastFS); + resume_thread(rpcThread); + } + + counter++; + } + + release_sem(connectSem); +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = *((int32 *) &packet->buffer[packet->offset]); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = *((int64 *) &packet->buffer[packet->offset]); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = *((int32 *) &packet->buffer[packet->offset]); + packet->offset += sizeof(bytes); + if (!bytes) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + memcpy(str, &packet->buffer[packet->offset], bytes); + str[bytes] = 0; + + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return 0; + + bytes = *((int32 *) &packet->buffer[packet->offset]); + packet->offset += sizeof(bytes); + if (!bytes) + return 0L; + + if (length < bytes) + return ERANGE; + + memcpy(buffer, &packet->buffer[packet->offset], bytes); + packet->offset += bytes; + return bytes; +} + +int btRPCGetHandle(bt_inPacket *packet, btFileHandle *fhandle) +{ + memcpy(fhandle->opaque, &packet->buffer[packet->offset], BT_FILE_HANDLE_SIZE); + packet->offset += BT_FILE_HANDLE_SIZE; + return B_OK; +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = value; + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = value; + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutHandle(bt_outPacket *packet, btFileHandle *fhandle) +{ + if (packet && fhandle) + { + btRPCGrowPacket(packet, BT_FILE_HANDLE_SIZE); + memcpy(&packet->buffer[packet->length], fhandle->opaque, BT_FILE_HANDLE_SIZE); + packet->length += BT_FILE_HANDLE_SIZE; + } +} + +int btRPCGetStat(bt_inPacket *packet, struct stat *st) +{ + st->st_dev = 0; + st->st_nlink = btRPCGetInt32(packet); + st->st_uid = btRPCGetInt32(packet); + st->st_gid = btRPCGetInt32(packet); + st->st_size = btRPCGetInt64(packet); + st->st_blksize = btRPCGetInt32(packet); + st->st_rdev = btRPCGetInt32(packet); + st->st_ino = btRPCGetInt64(packet); + st->st_mode = btRPCGetInt32(packet); + st->st_atime = btRPCGetInt32(packet); + st->st_mtime = btRPCGetInt32(packet); + st->st_ctime = btRPCGetInt32(packet); +} + +void btRPCPutStat(bt_outPacket *packet, struct stat *st) +{ + if (packet && st) + { + btRPCPutInt32(packet, (int) st->st_nlink); + btRPCPutInt32(packet, (int) st->st_uid); + btRPCPutInt32(packet, (int) st->st_gid); + btRPCPutInt64(packet, (int64) st->st_size); + btRPCPutInt32(packet, (int) st->st_blksize); + btRPCPutInt32(packet, (int) st->st_rdev); + btRPCPutInt64(packet, (int64) st->st_ino); + btRPCPutInt32(packet, (int) st->st_mode); + btRPCPutInt32(packet, (int) st->st_atime); + btRPCPutInt32(packet, (int) st->st_mtime); + btRPCPutInt32(packet, (int) st->st_ctime); + } +} + +void btEmptyLPBCache(btCookie *cookie) +{ + if (cookie->lpbCache) + { + cookie->lpbCache = false; + if (cookie->inPacket.buffer) + { + free(cookie->inPacket.buffer); + cookie->inPacket.buffer = NULL; + } + } +} + +// btMount() +// +int btMount(int session, char *shareName, btFileHandle *rootNode) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_MOUNT, 1, strlen(shareName)); + btRPCPutArg(outPacket, B_STRING_TYPE, shareName, strlen(shareName)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + btRPCGetHandle(inPacket, rootNode); + } + + btRPCRemoveCall(call); + } + + return error; +} + +// btLookup() +// +int btLookup(int session, btFileHandle *dhandle, char *file, btFileHandle *fhandle, struct stat *st) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_LOOKUP, 2, BT_FILE_HANDLE_SIZE + strlen(file)); + btRPCPutArg(outPacket, B_STRING_TYPE, dhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, file, strlen(file)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + btRPCGetHandle(inPacket, fhandle); + btRPCGetStat(inPacket, st); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +// btStat() +// +int btStat(int session, btFileHandle *fhandle, struct stat *st) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_STAT, 1, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, fhandle->opaque, BT_FILE_HANDLE_SIZE); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + btRPCGetStat(inPacket, st); + } + + btRPCRemoveCall(call); + } + + return error; +} + +// btGetFSInfo() +// +int btGetFSInfo(int session, btFileHandle *root, bt_fsinfo *fsinfo) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_FSINFO, 1, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, root->opaque, BT_FILE_HANDLE_SIZE); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + fsinfo->blockSize = btRPCGetInt32(inPacket); + fsinfo->totalBlocks = btRPCGetInt32(inPacket); + fsinfo->freeBlocks = btRPCGetInt32(inPacket); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +// btReadDir() +// +int btReadDir(int session, btFileHandle *dhandle, vnode_id *vnid, char **filename, btCookie *cookie, btFileHandle *fhandle, struct stat *st) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + char *mimeType; + int error, value; + + error = EHOSTUNREACH; + call = NULL; + inPacket = NULL; + *filename = NULL; + *vnid = 0; + + if (cookie->eof) + return ENOENT; + + // If no entries are currently cached, construct a call to the server to + // obtain the next series of directory entries. + if (cookie->lpbCache) + { + // If we had an existing packet buffer stored, remove it now. + inPacket = &cookie->inPacket; + if (inPacket->offset >= inPacket->length) + btEmptyLPBCache(cookie); + } + + if (!cookie->lpbCache) + { + outPacket = btRPCPutHeader(BT_CMD_READDIR, 2, BT_FILE_HANDLE_SIZE + BT_COOKIE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, dhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, cookie->opaque, BT_COOKIE_SIZE); + call = btRPCInvoke(session,"outPacket, false); + + if (call) + { + cookie->inPacket.buffer = (char *) malloc(call->inPacket->length); + if (cookie->inPacket.buffer) + { + inPacket = &cookie->inPacket; + memcpy(inPacket->buffer, call->inPacket->buffer, call->inPacket->length); + inPacket->length = call->inPacket->length; + inPacket->offset = 0; + cookie->lpbCache = true; + } + } + } + + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *vnid = btRPCGetInt64(inPacket); + *filename = btRPCGetNewString(inPacket); + if (!*filename) + return ENOENT; + + value = btRPCGetInt32(inPacket); + memcpy(cookie->opaque, &value, sizeof(value)); + btRPCGetHandle(inPacket, fhandle); + btRPCGetStat(inPacket, st); + } + else + { + btEmptyLPBCache(cookie); + cookie->eof = true; + } + } + + if (call) + btRPCRemoveCall(call); + + return error; +} + +// btRead() +// +size_t btRead(int session, btFileHandle *fhandle, off_t pos, size_t len, char *buf) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + struct stat st; + size_t bytesRead, filePos; + int32 byteCount; + int error; + + error = B_OK; + bytesRead = 0; + filePos = pos; + + // Get the file size from the server and verify we're not going beyond it. + // If we're already positioned at the end of the file, there's no point in + // trying to read any further. + btStat(session, fhandle, &st); + if (filePos >= st.st_size) + return 0; + + while (filePos < st.st_size && bytesRead < len && error == B_OK) + { + byteCount = min(BT_MAX_IO_BUFFER, len - bytesRead); + + outPacket = btRPCPutHeader(BT_CMD_READ, 3, BT_FILE_HANDLE_SIZE + 8); + btRPCPutArg(outPacket, B_STRING_TYPE, fhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_INT32_TYPE, &filePos, sizeof(filePos)); + btRPCPutArg(outPacket, B_INT32_TYPE, &byteCount, sizeof(byteCount)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + int32 bytesRecv; + bytesRecv = btRPCGetString(inPacket, buf + bytesRead, byteCount); + bytesRead += bytesRecv; + filePos += bytesRecv; + } + } + + btRPCRemoveCall(call); + } + } + + return bytesRead; +} + +// btWrite() +// +size_t btWrite(int session, btFileHandle *fhandle, off_t pos, size_t len, char *buf) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + struct stat st; + size_t bytesWritten; + int32 byteCount; + int error; + off_t curPos; + + error = B_OK; + bytesWritten = 0; + curPos = pos; + + // Get the file size from the server and verify we're not going beyond it. + // If we're already positioned at the end of the file, there's no point in + // trying to write any further. + btStat(session, fhandle, &st); + if (pos > st.st_size + 1) + return 0; + + while (bytesWritten < len && error == B_OK) + { + byteCount = min(BT_MAX_IO_BUFFER, len - bytesWritten); + + outPacket = btRPCPutHeader(BT_CMD_WRITE, 4, BT_FILE_HANDLE_SIZE + 12 + byteCount); + btRPCPutArg(outPacket, B_STRING_TYPE, fhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_INT64_TYPE, &curPos, sizeof(curPos)); + btRPCPutArg(outPacket, B_INT32_TYPE, &byteCount, sizeof(byteCount)); + btRPCPutArg(outPacket, B_STRING_TYPE, buf + bytesWritten, byteCount); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + int bytes = btRPCGetInt32(inPacket); + bytesWritten += bytes; + curPos += bytes; + } + } + + btRPCRemoveCall(call); + } + else + error = EHOSTUNREACH; + } + + return bytesWritten; +} + +int btCreate(int session, btFileHandle *dhandle, char *name, btFileHandle *fhandle, int omode, int perms, struct stat *st) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_CREATE, 4, BT_FILE_HANDLE_SIZE + strlen(name) + 8); + btRPCPutArg(outPacket, B_STRING_TYPE, dhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_INT32_TYPE, &omode, sizeof(omode)); + btRPCPutArg(outPacket, B_INT32_TYPE, &perms, sizeof(perms)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + btRPCGetHandle(inPacket, fhandle); + btRPCGetStat(inPacket, st); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btTruncate(int session, btFileHandle *fhandle, int64 len) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_TRUNCATE, 2, BT_FILE_HANDLE_SIZE + 8); + btRPCPutArg(outPacket, B_STRING_TYPE, fhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_INT64_TYPE, &len, sizeof(len)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btUnlink(int session, btFileHandle *dhandle, char *name) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_UNLINK, 2, BT_FILE_HANDLE_SIZE + strlen(name)); + btRPCPutArg(outPacket, B_STRING_TYPE, dhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btCreateDir(int session, btFileHandle *dhandle, char *name, int perms, btFileHandle *fhandle, struct stat *st) + +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_MKDIR, 3, BT_FILE_HANDLE_SIZE + strlen(name) + 4); + btRPCPutArg(outPacket, B_STRING_TYPE, dhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_INT32_TYPE, &perms, sizeof(perms)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + btRPCGetHandle(inPacket, fhandle); + btRPCGetStat(inPacket, st); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btRename(int session, btFileHandle *oldDHandle, char *oldName, btFileHandle *newDHandle, char *newName) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_RENAME, 4, 2 * BT_FILE_HANDLE_SIZE + strlen(oldName) + strlen(newName)); + btRPCPutArg(outPacket, B_STRING_TYPE, oldDHandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, oldName, strlen(oldName)); + btRPCPutArg(outPacket, B_STRING_TYPE, newDHandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, newName, strlen(newName)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btDeleteDir(int session, btFileHandle *dhandle, char *name) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_RMDIR, 2, BT_FILE_HANDLE_SIZE + strlen(name)); + btRPCPutArg(outPacket, B_STRING_TYPE, dhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btReadLink(int session, btFileHandle *fhandle, char *buf, size_t *bufsize) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_READLINK, 1, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, fhandle->opaque, BT_FILE_HANDLE_SIZE); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *bufsize = (size_t) btRPCGetInt32(inPacket); + if (*bufsize > 0) + btRPCGetString(inPacket, buf, (int) *bufsize); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btSymLink(int session, btFileHandle *dhandle, char *name, char *path) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_SYMLINK, 3, BT_FILE_HANDLE_SIZE + strlen(name) + strlen(path)); + btRPCPutArg(outPacket, B_STRING_TYPE, dhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_STRING_TYPE, path, strlen(path)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btWStat(int session, btFileHandle *fhandle, struct stat *st, long mask) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_WSTAT, 8, BT_FILE_HANDLE_SIZE + 28); + btRPCPutArg(outPacket, B_STRING_TYPE, fhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_INT32_TYPE, &mask, sizeof(mask)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_mode, sizeof(int32)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_uid, sizeof(int32)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_gid, sizeof(int32)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_size, sizeof(int32)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_atime, sizeof(int32)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_mtime, sizeof(int32)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btReadAttrib(int session, btFileHandle *fhandle, char *name, int type, void *buffer, size_t len, off_t pos) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + int32 bytesRead; + int32 newlen = (int32) len; + int32 newpos = (int32) pos; + + bytesRead = -1; + + outPacket = btRPCPutHeader(BT_CMD_READATTRIB, 5, BT_FILE_HANDLE_SIZE + strlen(name) + 12); + btRPCPutArg(outPacket, B_STRING_TYPE, fhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_INT32_TYPE, &type, sizeof(type)); + btRPCPutArg(outPacket, B_INT32_TYPE, &newpos, sizeof(newpos)); + btRPCPutArg(outPacket, B_INT32_TYPE, &newlen, sizeof(newlen)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + bytesRead = btRPCGetInt32(inPacket); + if (bytesRead > 0) + btRPCGetString(inPacket, (char *) buffer, len); + } + else + { + bytesRead = -1; + errno = error; + } + } + + btRPCRemoveCall(call); + } + + return bytesRead; +} + +int btWriteAttrib(int session, btFileHandle *fhandle, char *name, int type, void *buffer, size_t len, off_t pos) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + int32 bytesWritten; + int32 newlen = (int32) len; + int32 newpos = (int32) pos; + + bytesWritten = -1; + + outPacket = btRPCPutHeader(BT_CMD_WRITEATTRIB, 6, BT_FILE_HANDLE_SIZE + strlen(name) + len + 12); + btRPCPutArg(outPacket, B_STRING_TYPE, fhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_INT32_TYPE, &type, sizeof(type)); + btRPCPutArg(outPacket, B_STRING_TYPE, buffer, len); + btRPCPutArg(outPacket, B_INT32_TYPE, &newpos, sizeof(newpos)); + btRPCPutArg(outPacket, B_INT32_TYPE, &newlen, sizeof(newlen)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + bytesWritten = btRPCGetInt32(inPacket); + else + { + bytesWritten = -1; + errno = error; + } + } + + btRPCRemoveCall(call); + } + + return bytesWritten; +} + +int btReadAttribDir(int session, btFileHandle *fhandle, char **attrName, btCookie *cookie) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error, value; + + error = EHOSTUNREACH; + call = NULL; + inPacket = NULL; + *attrName = NULL; + + if (cookie->eof) + return ENOENT; + + // If no entries are currently cached, construct a call to the server to + // obtain the next series of directory entries. + if (cookie->lpbCache) + { + // If we had an existing packet buffer stored, remove it now. + inPacket = &cookie->inPacket; + if (inPacket->offset >= inPacket->length) + btEmptyLPBCache(cookie); + } + + if (!cookie->lpbCache) + { + outPacket = btRPCPutHeader(BT_CMD_READATTRIBDIR, 2, BT_FILE_HANDLE_SIZE + BT_COOKIE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, fhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, cookie->opaque, BT_COOKIE_SIZE); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + cookie->inPacket.buffer = (char *) malloc(call->inPacket->length); + if (cookie->inPacket.buffer) + { + inPacket = &cookie->inPacket; + memcpy(inPacket->buffer, call->inPacket->buffer, call->inPacket->length); + inPacket->length = call->inPacket->length; + inPacket->offset = 0; + cookie->lpbCache = true; + } + } + } + + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *attrName = btRPCGetNewString(inPacket); + if (!*attrName) + return ENOENT; + + value = btRPCGetInt32(inPacket); + memcpy(cookie->opaque, &value, sizeof(value)); + } + else + { + btEmptyLPBCache(cookie); + cookie->eof = true; + } + } + + if (call) + btRPCRemoveCall(call); + + return error; +} + +int btRemoveAttrib(int session, btFileHandle *fhandle, char *name) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_REMOVEATTRIB, 2, BT_FILE_HANDLE_SIZE + strlen(name)); + btRPCPutArg(outPacket, B_STRING_TYPE, fhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btStatAttrib(int session, btFileHandle *fhandle, char *name, struct attr_info *info) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_STATATTRIB, 2, BT_FILE_HANDLE_SIZE + strlen(name)); + btRPCPutArg(outPacket, B_STRING_TYPE, fhandle->opaque, BT_FILE_HANDLE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + info->type = btRPCGetInt32(inPacket); + info->size = btRPCGetInt64(inPacket); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btReadIndexDir(int session, char **indexName, int bufLength, btCookie *cookie) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error, value; + + error = EHOSTUNREACH; + *indexName = NULL; + + if (cookie->eof) + return ENOENT; + + outPacket = btRPCPutHeader(BT_CMD_READINDEXDIR, 1, BT_COOKIE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, cookie->opaque, BT_COOKIE_SIZE); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *indexName = btRPCGetNewString(inPacket); + value = btRPCGetInt32(inPacket); + memcpy(cookie->opaque, &value, sizeof(value)); + } + else + cookie->eof = true; + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btCreateIndex(int session, char *name, int type, int flags) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_CREATEINDEX, 3, strlen(name) + 8); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_INT32_TYPE, &type, sizeof(type)); + btRPCPutArg(outPacket, B_INT32_TYPE, &flags, sizeof(flags)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btRemoveIndex(int session, char *name) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_REMOVEINDEX, 1, strlen(name)); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btStatIndex(int session, char *name, struct index_info *buf) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_STATINDEX, 1, strlen(name)); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + buf->type = btRPCGetInt32(inPacket); + buf->size = btRPCGetInt64(inPacket); + buf->modification_time = btRPCGetInt32(inPacket); + buf->creation_time = btRPCGetInt32(inPacket); + buf->uid = btRPCGetInt32(inPacket); + buf->gid = btRPCGetInt32(inPacket); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btReadQuery(int session, char **fileName, int64 *inode, btQueryCookie *cookie) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error, value; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_READQUERY, 2, BT_QUERY_COOKIE_SIZE + strlen(cookie->query)); + btRPCPutArg(outPacket, B_STRING_TYPE, cookie->opaque, BT_QUERY_COOKIE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, cookie->query, strlen(cookie->query)); + call = btRPCInvoke(session, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *inode = btRPCGetInt64(inPacket); + *fileName = btRPCGetNewString(inPacket); + if (!*fileName) + error = ENOENT; + + value = btRPCGetInt32(inPacket); + memcpy(cookie->opaque, &value, sizeof(value)); + } + } + + btRPCRemoveCall(call); + } + + return error; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/fsproto.h b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/fsproto.h new file mode 100644 index 0000000000..a6072837d5 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/fsproto.h @@ -0,0 +1,246 @@ +#ifndef _FSPROTO_H +#define _FSPROTO_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef dev_t nspace_id; +typedef ino_t vnode_id; + +/* UGLY UGLY UGLY */ +#ifndef _DRIVERS_H +struct selectsync; +typedef struct selectsync selectsync; +#endif + + +/* + * PUBLIC PART OF THE FILE SYSTEM PROTOCOL + */ + +#define WSTAT_MODE 0x0001 +#define WSTAT_UID 0x0002 +#define WSTAT_GID 0x0004 +#define WSTAT_SIZE 0x0008 +#define WSTAT_ATIME 0x0010 +#define WSTAT_MTIME 0x0020 +#define WSTAT_CRTIME 0x0040 + +#define WFSSTAT_NAME 0x0001 + +#define B_ENTRY_CREATED 1 +#define B_ENTRY_REMOVED 2 +#define B_ENTRY_MOVED 3 +#define B_STAT_CHANGED 4 +#define B_ATTR_CHANGED 5 +#define B_DEVICE_MOUNTED 6 +#define B_DEVICE_UNMOUNTED 7 + +#define B_STOP_WATCHING 0x0000 +#define B_WATCH_NAME 0x0001 +#define B_WATCH_STAT 0x0002 +#define B_WATCH_ATTR 0x0004 +#define B_WATCH_DIRECTORY 0x0008 + +#define SELECT_READ 1 +#define SELECT_WRITE 2 +#define SELECT_EXCEPTION 3 + +#define B_CUR_FS_API_VERSION 2 + +struct attr_info; +struct index_info; + +typedef int op_read_vnode(void *ns, vnode_id vnid, char r, void **node); +typedef int op_write_vnode(void *ns, void *node, char r); +typedef int op_remove_vnode(void *ns, void *node, char r); +typedef int op_secure_vnode(void *ns, void *node); + +typedef int op_walk(void *ns, void *base, const char *file, char **newpath, + vnode_id *vnid); + +typedef int op_access(void *ns, void *node, int mode); + +typedef int op_create(void *ns, void *dir, const char *name, + int omode, int perms, vnode_id *vnid, void **cookie); +typedef int op_mkdir(void *ns, void *dir, const char *name, int perms); +typedef int op_symlink(void *ns, void *dir, const char *name, + const char *path); +typedef int op_link(void *ns, void *dir, const char *name, void *node); + +typedef int op_rename(void *ns, void *olddir, const char *oldname, + void *newdir, const char *newname); +typedef int op_unlink(void *ns, void *dir, const char *name); +typedef int op_rmdir(void *ns, void *dir, const char *name); + +typedef int op_readlink(void *ns, void *node, char *buf, size_t *bufsize); + +typedef int op_opendir(void *ns, void *node, void **cookie); +typedef int op_closedir(void *ns, void *node, void *cookie); +typedef int op_rewinddir(void *ns, void *node, void *cookie); +typedef int op_readdir(void *ns, void *node, void *cookie, long *num, + struct dirent *buf, size_t bufsize); + +typedef int op_open(void *ns, void *node, int omode, void **cookie); +typedef int op_close(void *ns, void *node, void *cookie); +typedef int op_free_cookie(void *ns, void *node, void *cookie); +typedef int op_read(void *ns, void *node, void *cookie, off_t pos, void *buf, + size_t *len); +typedef int op_write(void *ns, void *node, void *cookie, off_t pos, + const void *buf, size_t *len); +typedef int op_readv(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, + size_t count, size_t *len); +typedef int op_writev(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, + size_t count, size_t *len); +typedef int op_ioctl(void *ns, void *node, void *cookie, int cmd, void *buf, + size_t len); +typedef int op_setflags(void *ns, void *node, void *cookie, int flags); + +typedef int op_rstat(void *ns, void *node, struct stat *); +typedef int op_wstat(void *ns, void *node, struct stat *, long mask); +typedef int op_fsync(void *ns, void *node); + +typedef int op_select(void *ns, void *node, void *cookie, uint8 event, + uint32 ref, selectsync *sync); +typedef int op_deselect(void *ns, void *node, void *cookie, uint8 event, + selectsync *sync); + +typedef int op_initialize(const char *devname, void *parms, size_t len); +typedef int op_mount(nspace_id nsid, const char *devname, ulong flags, + void *parms, size_t len, void **data, vnode_id *vnid); +typedef int op_unmount(void *ns); +typedef int op_sync(void *ns); +typedef int op_rfsstat(void *ns, struct fs_info *); +typedef int op_wfsstat(void *ns, struct fs_info *, long mask); + + +typedef int op_open_attrdir(void *ns, void *node, void **cookie); +typedef int op_close_attrdir(void *ns, void *node, void *cookie); +typedef int op_rewind_attrdir(void *ns, void *node, void *cookie); +typedef int op_read_attrdir(void *ns, void *node, void *cookie, long *num, + struct dirent *buf, size_t bufsize); +typedef int op_remove_attr(void *ns, void *node, const char *name); +typedef int op_rename_attr(void *ns, void *node, const char *oldname, + const char *newname); +typedef int op_stat_attr(void *ns, void *node, const char *name, + struct attr_info *buf); + +typedef int op_write_attr(void *ns, void *node, const char *name, int type, + const void *buf, size_t *len, off_t pos); +typedef int op_read_attr(void *ns, void *node, const char *name, int type, + void *buf, size_t *len, off_t pos); + +typedef int op_open_indexdir(void *ns, void **cookie); +typedef int op_close_indexdir(void *ns, void *cookie); +typedef int op_rewind_indexdir(void *ns, void *cookie); +typedef int op_read_indexdir(void *ns, void *cookie, long *num, + struct dirent *buf, size_t bufsize); +typedef int op_create_index(void *ns, const char *name, int type, int flags); +typedef int op_remove_index(void *ns, const char *name); +typedef int op_rename_index(void *ns, const char *oldname, + const char *newname); +typedef int op_stat_index(void *ns, const char *name, struct index_info *buf); + +typedef int op_open_query(void *ns, const char *query, ulong flags, + port_id port, long token, void **cookie); +typedef int op_close_query(void *ns, void *cookie); +typedef int op_read_query(void *ns, void *cookie, long *num, + struct dirent *buf, size_t bufsize); + +typedef struct vnode_ops { + op_read_vnode (*read_vnode); + op_write_vnode (*write_vnode); + op_remove_vnode (*remove_vnode); + op_secure_vnode (*secure_vnode); + op_walk (*walk); + op_access (*access); + op_create (*create); + op_mkdir (*mkdir); + op_symlink (*symlink); + op_link (*link); + op_rename (*rename); + op_unlink (*unlink); + op_rmdir (*rmdir); + op_readlink (*readlink); + op_opendir (*opendir); + op_closedir (*closedir); + op_free_cookie (*free_dircookie); + op_rewinddir (*rewinddir); + op_readdir (*readdir); + op_open (*open); + op_close (*close); + op_free_cookie (*free_cookie); + op_read (*read); + op_write (*write); + op_readv (*readv); + op_writev (*writev); + op_ioctl (*ioctl); + op_setflags (*setflags); + op_rstat (*rstat); + op_wstat (*wstat); + op_fsync (*fsync); + op_initialize (*initialize); + op_mount (*mount); + op_unmount (*unmount); + op_sync (*sync); + op_rfsstat (*rfsstat); + op_wfsstat (*wfsstat); + op_select (*select); + op_deselect (*deselect); + op_open_indexdir (*open_indexdir); + op_close_indexdir (*close_indexdir); + op_free_cookie (*free_indexdircookie); + op_rewind_indexdir (*rewind_indexdir); + op_read_indexdir (*read_indexdir); + op_create_index (*create_index); + op_remove_index (*remove_index); + op_rename_index (*rename_index); + op_stat_index (*stat_index); + op_open_attrdir (*open_attrdir); + op_close_attrdir (*close_attrdir); + op_free_cookie (*free_attrdircookie); + op_rewind_attrdir (*rewind_attrdir); + op_read_attrdir (*read_attrdir); + op_write_attr (*write_attr); + op_read_attr (*read_attr); + op_remove_attr (*remove_attr); + op_rename_attr (*rename_attr); + op_stat_attr (*stat_attr); + op_open_query (*open_query); + op_close_query (*close_query); + op_free_cookie (*free_querycookie); + op_read_query (*read_query); +} vnode_ops; + +extern _IMPEXP_KERNEL int new_path(const char *path, char **copy); +extern _IMPEXP_KERNEL void free_path(char *p); + +extern _IMPEXP_KERNEL int notify_listener(int op, nspace_id nsid, + vnode_id vnida, vnode_id vnidb, + vnode_id vnidc, const char *name); +extern _IMPEXP_KERNEL void notify_select_event(selectsync *sync, uint32 ref); +extern _IMPEXP_KERNEL int send_notification(port_id port, long token, + ulong what, long op, nspace_id nsida, + nspace_id nsidb, vnode_id vnida, + vnode_id vnidb, vnode_id vnidc, + const char *name); +extern _IMPEXP_KERNEL int get_vnode(nspace_id nsid, vnode_id vnid, void **data); +extern _IMPEXP_KERNEL int put_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int new_vnode(nspace_id nsid, vnode_id vnid, void *data); +extern _IMPEXP_KERNEL int remove_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int unremove_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int is_vnode_removed(nspace_id nsid, vnode_id vnid); + + +extern _EXPORT vnode_ops fs_entry; +extern _EXPORT int32 api_version; + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/makefile b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/makefile new file mode 100644 index 0000000000..5e8eb7ef7e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/makefile @@ -0,0 +1,319 @@ +## BeOS Generic Makefile ## + +## Fill in the top section of this makefile to define exactly what sort of +## binary you are creating, and what sources, resources and libraries are +## needed to create it. The makefile will then determine the proper +## platform specific options. + +## Fill in the top section to define the binary being created and the makefile +## will make sure that all of the hard work is taken care of for you, for both +## PowerPC and Intel versions of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= betalk + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= DRIVER + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= nfs_add_on.c btClient.c + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +#specify additional libraries to link against +# if libName.so or libName.a is the name of the library to link against +# then simply specify Name in the LIBS list +# if there is another naming scheme use the full binary +# name: my_library.so or my_lib.a +# libroot.so never needs to be specified here, although libbe.so does +LIBS= ksocket + +# specify the paths to directories where additional +# libraries are to be found. /boot/develop/lib/PLATFORM/ is +# already set. The paths can be full or relative to this +# makefile. The paths included may not be recursive, so +# specify all of the needed paths explicitly +# Directories containing source-files are automatically added. +LIBPATHS=ksocket_v3/libksocket/$(OBJ_DIR) + +# specify additional directories where header files can be found +# directories where sources are found are included automatically +# included. +INCPATHS= ksocket_v3/libksocket + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= + +# specify any symbols to be defined. The symbols will be +# set to a value of 1. For example specify DEBUG if you want +# DEBUG=1 to be set when compiling. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = + +# specify symbols +# if TRUE debug symbols will be created +SYMBOLS = + + +## Generic Makefile Rules --------------------------- +## DO NOT MODIFY BENEATH THIS LINE ----------------- + +# determine wheather running on x86 or ppc +MACHINE=$(shell uname -m) +ifeq ($(MACHINE), BePC) + CPU = x86 +else + CPU = ppc +endif + +# set the directory where object files and binaries will be created + OBJ_DIR := obj.$(CPU) + +# specify that the binary should be created in the object directory + TARGET := $(OBJ_DIR)/$(NAME) + +# specify the mimeset tool + MIMESET := mimeset + +# specify the tools for adding and removing resources + XRES = xres + +# SETTING: define debug symbols if desired +ifeq ($(SYMBOLS), TRUE) + CFLAGS += -g +endif + + +# platform specific settings + +# x86 Settings +ifeq ($(CPU), x86) +# set the compiler and compiler flags + CC = gcc + ##!! change next time : drivers get -no-fpic and -fpic goes away !! + CFLAGS += -fpic + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O1 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy + else + ifeq ($(WARNINGS), NONE) + + endif + endif + +# set the linker and linker flags + LD = gcc + LDFLAGS = + +# SETTING: set linker flags for each binary type + ifeq ($(TYPE), APP) + LDFLAGS += -Xlinker -soname=_APP_ + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -addon -Xlinker -soname=$(NAME) + else + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_ + endif + endif + endif + +else + +# ppc Settings +ifeq ($(CPU), ppc) +# set the compiler and compiler flags + CC = mwcc + CFLAGS += + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O7 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -w all + else + ifeq ($(WARNINGS), NONE) + CFLAGS += -w 0 + endif + endif + + # clear the standard environment variable + # now there are no standard libraries to link against + BELIBFILES= + +# set the linker and linker flags + LD = mwldppc + + ifeq ($(TYPE), APP) + LDFLAGS += + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -xms + endif + endif + + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nodefaults \ + -export all \ + -G \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/_KERNEL_ + else + # override the standard environment variable + LDFLAGS += -export pragma \ + -init _init_routine_ \ + -term _term_routine_ \ + -lroot \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/init_term_dyn.o \ + /boot/develop/lib/ppc/start_dyn.o + + endif + + +endif +endif + + +# psuedo-function for converting a list of source files in SRCS variable +# to a corresponding list of object files in $(OBJ_DIR)/xxx.o +# The "function" strips off the src file suffix (.ccp or .c or whatever) +# and then strips of the directory name, leaving just the root file name. +# It then appends the .o suffix and prepends the $(OBJ_DIR)/ path +define SRCS_LIST_TO_OBJS + $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ + $(basename $(notdir $(file)))))) +endef + +OBJS = $(SRCS_LIST_TO_OBJS) + +# create a unique list of paths to our sourcefiles +SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) + +# add source paths to VPATH if not already present +VPATH := +VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) + +# add source paths and include paths to INLCUDES if not already present +INCLUDES = $(foreach path, $(INCPATHS) $(SRC_PATHS), $(addprefix -I, $(path))) + + +# SETTING: add the -L prefix to all library paths to search +LINK_PATHS = $(foreach path, $(LIBPATHS) $(SRC_PATHS) , \ + $(addprefix -L, $(path))) + +# SETTING: add the -l prefix to all libs to be linked against +LINK_LIBS = $(foreach lib, $(LIBS), $(addprefix -l, $(lib))) + +# add to the linker flags +LDFLAGS += $(LINK_PATHS) $(LINK_LIBS) + +# SETTING: add the defines to the compiler flags +CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define))) + +# SETTING: use the archive tools if building a static library +# otherwise use the linker +ifeq ($(TYPE), STATIC) + BUILD_LINE = ar -cru $(NAME) $(OBJS) +else + BUILD_LINE = $(LD) -o $@ $(OBJS) $(LDFLAGS) +endif + +# create the resource instruction + ifeq ($(RSRCS), ) + DO_RSRCS := + else + DO_RSRCS := $(XRES) -o $(TARGET) $(RSRCS) + endif + + +# define the actual work to be done +default: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) $(RSRCS) ksocket_v3/libksocket/$(OBJ_DIR)/libksocket.a + $(BUILD_LINE) + $(DO_RSRCS) + $(MIMESET) -f $@ + + +# rule to create the object file directory if needed +$(OBJ_DIR):: + @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 + +$(OBJ_DIR)/%.o : %.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cpp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.C + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CC + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CPP + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ + + +# empty rule. Things that depend on this rule will always get triggered +FORCE: + +# The generic clean command. Delete everything in the object folder. +clean :: FORCE + -rm -rf $(OBJ_DIR) + +# remove just the application from the object folder +rmapp :: + -rm -f $(TARGET) + +ksocket_v3/libksocket/$(OBJ_DIR)/libksocket.a :: FORCE + cd ksocket_v3/libksocket; make diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/nfs_add_on.c b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/nfs_add_on.c new file mode 100644 index 0000000000..f72aa53d6f --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/nfs_add_on.c @@ -0,0 +1,1295 @@ +#define _BUILDING_fs 1 + +#include "betalk.h" +#include "nfs_add_on.h" + +#include "ksocket.h" +#include +#include +#include +#include +#include +#include + +_EXPORT vnode_ops fs_entry = +{ + (op_read_vnode *) &fs_read_vnode, + (op_write_vnode *) &fs_write_vnode, + (op_remove_vnode *) &fs_remove_vnode, + (op_secure_vnode *) &fs_secure_vnode, + (op_walk *) &fs_walk, + (op_access *) &fs_access, + (op_create *) &fs_create, + (op_mkdir *) &fs_mkdir, + (op_symlink *) &fs_symlink, + NULL, // &fs_link, + (op_rename *) &fs_rename, + (op_unlink *) &fs_unlink, + (op_rmdir *) &fs_rmdir, + (op_readlink *) &fs_readlink, + (op_opendir *) &fs_opendir, + (op_closedir *) &fs_closedir, + (op_free_cookie *) &fs_free_dircookie, + (op_rewinddir *) &fs_rewinddir, + (op_readdir *) &fs_readdir, + (op_open *) &fs_open, + (op_close *) &fs_close, + (op_free_cookie *) &fs_free_cookie, + (op_read *) &fs_read, + (op_write *) &fs_write, + NULL, // &fs_readv + NULL, // &fs_writev + NULL, // &fs_ioctl, + NULL, // &fs_setflags, + (op_rstat *) &fs_rstat, + (op_wstat *) &fs_wstat, + NULL, // &fs_fsync, + NULL, // &fs_initialize, + (op_mount *) &fs_mount, + (op_unmount *) &fs_unmount, + NULL, // &fs_sync, + (op_rfsstat *) &fs_rfsstat, + (op_wfsstat *) &fs_wfsstat, + NULL, // &fs_select + NULL, // &fs_deselect + NULL, // (op_open_indexdir *) &fs_open_indexdir, + NULL, // (op_close_indexdir *) &fs_close_indexdir, + NULL, // (op_free_cookie *) &fs_free_indexdircookie, + NULL, // (op_rewind_indexdir *) &fs_rewind_indexdir, + NULL, // (op_read_indexdir *) &fs_read_indexdir, + NULL, // (op_create_index *) &fsCreateIndex, + NULL, // (op_remove_index *) &fsRemoveIndex, + NULL, // &fs_rename_index, + NULL, // (op_stat_index *) &fsStatIndex, + (op_open_attrdir *) &fs_open_attribdir, + (op_close_attrdir *) &fs_close_attribdir, + (op_free_cookie *) &fs_free_attribdircookie, + (op_rewind_attrdir *) &fs_rewind_attribdir, + (op_read_attrdir *) &fs_read_attribdir, + (op_write_attr *) &fs_write_attrib, + (op_read_attr *) &fs_read_attrib, + (op_remove_attr *) &fs_remove_attrib, + NULL, // &fs_rename_attrib, + (op_stat_attr *) &fs_stat_attrib, + (op_open_query *) &fsOpenQuery, + (op_close_query *) &fsCloseQuery, + (op_free_cookie *) &fsFreeQueryCookie, + (op_read_query *) &fsReadQuery +}; + +_EXPORT int32 api_version = B_CUR_FS_API_VERSION; + + +extern btFileHandle handle_from_vnid(fs_nspace *ns, vnode_id vnid) +{ + fs_node *current; + + while (acquire_sem(ns->sem) == B_INTERRUPTED); + + current = ns->first; + while (current && current->vnid != vnid) + current = current->next; + + release_sem(ns->sem); + + return current->fhandle; +} + +btFileHandle *create_node(fs_nspace *ns, btFileHandle *dir, btFileHandle *file, char *name, vnode_id vnid) +{ + fs_node *newNode = (fs_node *) malloc(sizeof(fs_node)); + if (newNode) + { +// newNode->dhandle = *dir; + newNode->fhandle = *file; +// strcpy(newNode->name, name); + newNode->vnid = vnid; + + insert_node(ns, newNode); + } + return newNode; +} + +void insert_node(fs_nspace *ns, fs_node *node) +{ + fs_node *current; + + while (acquire_sem(ns->sem) == B_INTERRUPTED); + + current = ns->first; + while (current && current->vnid != node->vnid) + current = current->next; + + if (current) + free(node); + else + { + node->next = ns->first; + ns->first = node; + } + + release_sem(ns->sem); +} + +void remove_node(fs_nspace *ns, vnode_id vnid) +{ + fs_node *current; + fs_node *previous; + + while (acquire_sem(ns->sem) == B_INTERRUPTED); + + current = ns->first; + previous = NULL; + + while (current && current->vnid != vnid) + { + previous = current; + current = current->next; + } + + if (current) + { + if (previous) + previous->next = current->next; + else + ns->first = current->next; + + free(current); + } + + release_sem(ns->sem); +} + +// fs_read_vnode() +// +// Description: Allocate resources required to load the specified vnid. Also returns +// a reference to the vnode via the supplied pointer. +// +// Parameters: +// ns (in): Private file system structure +// vnid (in): vnid of the vnode to load +// r (in): ?? +// node (out): A reference to the vnode loaded +// +// Returns: +// B_OK if everything is successful, or +// EINVAL if the specified vnid is not found +// +extern int fs_read_vnode(fs_nspace *ns, vnode_id vnid, char r, fs_node **node) +{ + fs_node *current; + + *node = NULL; + + // If we need to acquire the semaphone to search the list, do so now. + if (!r) + while (acquire_sem(ns->sem) == B_INTERRUPTED); + + current = ns->first; + while (current && current->vnid != vnid) + current = current->next; + + // TODO: shouldn't we release the semaphore here? + // If the specified parameter is non-null, then return the node we found. + if (current && node) + *node = current; + + // Release the semaphore if necessary. + if (!r) + release_sem(ns->sem); + + return (current ? B_OK : EINVAL); +} + +// fs_write_vnode() +// +// Description: Free resources allocated with the sister function fs_read_vnode(). +// Parameters: +// ns (in): Private file system structure +// node (in): Node that can be freed +// r (in): ?? +// Returns: +// B_OK if everything is successful (always in our case) +// +extern int fs_write_vnode(fs_nspace *ns, fs_node *node, char r) +{ + // In our case, there aren't any resources to free, so there isn't anything + // for this function to do but return successfully. + return B_OK; +} + +// fs_walk() +// +// Description: This function is the single file system location where a path is +// traversed by name. Given a directory handle and a file name, this function returns +// the vnid of the file if it indeed exists. +// +// Parameters: +// ns (in): Private file system structure +// base (in): File handle of the directory to look in +// file (in): Name of the file to look for +// newpath (out): Name of the real file if the given file is a symbolic link +// vnid (out): Vnid of the file given by "file" +// +// Returns: +// B_OK if everything is successful, +// Otherwise an error code detailing the problem +// +extern int fs_walk(fs_nspace *ns, fs_node *base, const char *file, char **newpath, vnode_id *vnid) +{ + bool isLink; + fs_node *dummy; + status_t result; + + // If the file specified is the current directory, then that parameter provides + // the necessary vnid. Also note that the current directory entry cannot be a + // symbolic link. + if (!strcmp(".", file)) + { + *vnid = base->vnid; + isLink = false; + } + else + { + btFileHandle fhandle; + struct stat st; + status_t result; + + // Look up the requested entry, getting the stat structure and file handle + // filled in. + if ((result = btLookup(ns->s, &base->fhandle, file, &fhandle, &st)) != B_OK) + return result; + + // The vnid is the resulting file's inode. Once this is established, insert + // the new node in our list. + if (create_node(ns, NULL, &fhandle, NULL, st.st_ino) == NULL) + return ENOMEM; + + *vnid = st.st_ino; + isLink = S_ISLNK(st.st_mode); + } + + if ((result = get_vnode(ns->nsid, *vnid, (void **) &dummy)) < B_OK) + return result; + + // If we've found a symbolic link, and the supplied character pointer is non-null, + // then the vnode layer is looking for the actual path. + if (isLink && newpath) + { + char path[B_PATH_NAME_LENGTH + 1]; + size_t pathLen = B_PATH_NAME_LENGTH; + + if ((result = fs_readlink(ns, dummy, path, &pathLen)) < B_OK) + { + put_vnode(ns->nsid, *vnid); + return result; + } + + path[pathLen] = 0; + result = new_path(path, newpath); + + if (result < B_OK) + { + put_vnode(ns->nsid, *vnid); + return result; + } + + return put_vnode(ns->nsid, *vnid); + } + + return B_OK; +} + +// fs_opendir() +// +extern int fs_opendir(fs_nspace *ns, fs_node *node, btCookie **cookie) +{ + struct stat st; + btFileHandle fhandle; + status_t result; + + // Do a basic stat() on this file to verify we indeed have a directory. + // If we cannot obtain this information, we have an even bigger problem. + if ((result = btStat(ns->s, &node->fhandle, &st)) < B_OK) + return result; + + // Now that we have the right information, verify we're looking at a directory. + if (!S_ISDIR(st.st_mode)) + return ENOTDIR; + + // Allocate and initialize the cookie. + *cookie = (btCookie *) malloc(sizeof(btCookie)); + if (!*cookie) + return ENOMEM; + + memset((*cookie)->opaque, 0, BT_COOKIE_SIZE); + (*cookie)->lpbCache = false; + (*cookie)->eof = false; + + return B_OK; +} + +// fs_closedir() +// +extern int fs_closedir(fs_nspace *ns, fs_node *node, btCookie *cookie) +{ + btEmptyLPBCache(cookie); + return B_OK; +} + +// fs_rewinddir() +// +extern int fs_rewinddir(fs_nspace *ns, fs_node *node, btCookie *cookie) +{ + memset(cookie->opaque, 0, BT_COOKIE_SIZE); + cookie->eof = false; + btEmptyLPBCache(cookie); + return B_OK; +} + +// fs_readdir() +// +extern int fs_readdir(fs_nspace *ns, fs_node *node, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize) +{ + btFileHandle fhandle; + struct stat st; + status_t result; + vnode_id vnid; + char *filename; + long max, bufContent; + int32 value; + + max = *num; + *num = 0; + + // Cause the directory to be read. + while ((result = btReadDir(ns->s, &node->fhandle, &vnid, &filename, cookie, &fhandle, &st)) == B_OK) + { + if (strcmp(filename, ".") && strcmp(filename, "..")) + { + fs_node *newNode = (fs_node *) malloc(sizeof(fs_node)); + newNode->vnid = vnid; + memcpy(&newNode->fhandle, &fhandle, BT_FILE_HANDLE_SIZE); + + insert_node (ns, newNode); + + bufContent = 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(filename) + 1; + if (bufsize < bufContent) + return B_OK; + + buf->d_dev = ns->nsid; + buf->d_pdev = ns->nsid; + buf->d_ino = vnid; + buf->d_pino = node->vnid; + buf->d_reclen = bufContent; + strcpy(buf->d_name, filename); + + bufsize -= bufContent; + buf = (struct dirent *)((char *) buf + bufContent); + + (*num)++; + } + + free(filename); + + if (*num == max) + return B_OK; + } + + return B_OK; +} + +// fs_free_dircookie() +// +extern int fs_free_dircookie(fs_nspace *ns, fs_node *node, btCookie *cookie) +{ + if (cookie) + { + btEmptyLPBCache(cookie); + free(cookie); + } + + return B_OK; +} + +// fs_rstat() +// +extern int fs_rstat(fs_nspace *ns, fs_node *node, struct stat *st) +{ + btFileHandle fhandle; + status_t result; + + // This was btGetAttr(), but isn't that just btStat()? + if ((result = btStat(ns->s, &node->fhandle, st)) < B_OK) + return result; + + st->st_dev = ns->nsid; + return B_OK; +} + +// fs_mount() +// +extern int fs_mount(nspace_id nsid, const char *devname, ulong flags, struct mount_bt_params *parms, size_t len, fs_nspace **data, vnode_id *vnid) +{ + status_t result; + fs_nspace *ns; + fs_node *rootNode; + struct stat st; + + // If we didn't receive any mount parameters, we won't know the server to connect to, + // or the folder to be shared. + if (parms == NULL) + return EINVAL; + + // Initialize the ksocket library for kernel-based network communication. + if ((result = ksocket_init()) < B_OK) + return result; + + // Allocate our private file system information block. + ns = (fs_nspace *) malloc(sizeof(fs_nspace)); + ns->nsid = nsid; + + // Copy over the parameters specified, including the server, folder, user and group + // IDs, and so on. + ns->params.serverIP = parms->serverIP; + ns->params.server = strdup(parms->server); + ns->params.export = strdup(parms->export); + ns->params.uid = parms->uid; + ns->params.gid = parms->gid; + ns->params.hostname = strdup(parms->hostname); + ns->params.folder = strdup(parms->folder); + + // Now connect to the remote server. The socket returned will be used for all future + // communication with that server. + ns->s = btConnect(ns->params.serverIP, BT_TCPIP_PORT); + if (ns->s != INVALID_SOCKET) + { + ns->xid=0; + + btRPCInit(ns); + + // Create a semaphore for exclusive access to the vnode list when we need to scan + // for a particular vnode. + ns->sem = create_sem(1, "bt_sem"); + if (ns->sem > 0) + { + // The system should own this semaphore. + set_sem_owner(ns->sem, B_SYSTEM_TEAM); + + // Allocate the root node. + rootNode = (fs_node *) malloc(sizeof(fs_node)); + rootNode->next = NULL; + + // Let the server know we are mounting the exported folder. This operation + // will return the root node file handle. + result = btMount(ns->s, ns->params.export, &rootNode->fhandle); + if (result == B_OK) + { + // This was btGetAttr() + result = btStat(ns->s, &rootNode->fhandle, &st); + if (result == B_OK) + { + ns->rootid = st.st_ino; + rootNode->vnid = ns->rootid; + *vnid = ns->rootid; + + result = new_vnode(nsid, *vnid, rootNode); + if (result == B_OK) + { + *data = ns; + ns->first = rootNode; + notify_listener(B_DEVICE_MOUNTED, ns->nsid, 0, 0, 0, NULL); + return B_OK; + } + } + } + + // We've failed. The first step is to free the root node we allocated, and + // release the semaphore we created as well. + free(rootNode); + delete_sem(ns->sem); + } + + // Disconnect from the server. + btDisconnect(ns->s); + btRPCClose(); + } + else + result = EHOSTUNREACH; + + // De-allocate our private file system structure and all the string space we duplicated + // on startup. + free(ns->params.hostname); + free(ns->params.export); + free(ns->params.server); + free(ns); + + ksocket_cleanup(); + return result; +} + +extern int fs_unmount(fs_nspace *ns) +{ + notify_listener(B_DEVICE_UNMOUNTED, ns->nsid, 0, 0, 0, NULL); + + btDisconnect(ns->s); + btRPCClose(); + + free(ns->params.hostname); + free(ns->params.export); + free(ns->params.server); + + while (acquire_sem(ns->sem) == B_INTERRUPTED); + + while (ns->first) + { + fs_node *next = ns->first->next; + free(ns->first); + ns->first = next; + } + + release_sem(ns->sem); + delete_sem(ns->sem); + + ns->s = INVALID_SOCKET; + free(ns); + ksocket_cleanup(); + + return B_OK; +} + +// fs_rfsstat() +// +extern int fs_rfsstat(fs_nspace *ns, struct fs_info *info) +{ + btFileHandle rootHandle = handle_from_vnid(ns, ns->rootid); + bt_fsinfo fsinfo; + int result; + + result = btGetFSInfo(ns->s, &rootHandle, &fsinfo); + if (result == B_OK) + { + info->dev = ns->nsid; + info->root = ns->rootid; + info->flags = B_FS_IS_SHARED | B_FS_IS_PERSISTENT | + B_FS_HAS_MIME | B_FS_HAS_ATTR | B_FS_HAS_QUERY; + info->block_size = fsinfo.blockSize; + info->io_size = 8192; + info->total_blocks = fsinfo.totalBlocks; + info->free_blocks = fsinfo.freeBlocks; + info->total_nodes = 100; + info->free_nodes = 100; + strcpy(info->device_name, "BeServed_Share"); + strcpy(info->volume_name, ns->params.folder); + strcpy(info->fsh_name, "bt_fsh"); + } + + return result; +} + +// fs_open() +// +extern int fs_open(fs_nspace *ns, fs_node *node, int omode, fs_file_cookie **cookie) +{ + struct stat st; + btFileHandle fhandle; + status_t result; + + // This was btGetAttr() + if ((result = btStat(ns->s, &node->fhandle, &st)) < B_OK) + return result; + + if (S_ISDIR(st.st_mode)) + { + *cookie = NULL; + return B_OK; // permit opening of directories + } + + *cookie = (fs_file_cookie *) malloc(sizeof(fs_file_cookie)); + (*cookie)->omode = omode; + (*cookie)->original_size = st.st_size; + (*cookie)->st = st; + + return B_OK; +} + +// fs_close() +// +extern int fs_close(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie) +{ + if (cookie && (cookie->omode & O_RDWR || cookie->omode & O_WRONLY)) + return notify_listener(B_STAT_CHANGED, ns->nsid, 0, 0, node->vnid, NULL); + + return B_OK; +} + +// fs_free_cookie() +// +extern int fs_free_cookie(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie) +{ + if (cookie) + free(cookie); + + return B_OK; +} + +// fs_read() +// +extern int fs_read(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, void *buf, size_t *len) +{ + if (!len) + return B_ERROR; + + // If we weren't given proper file system or vnode pointers, something is awry. + if (!ns || !node || !buf) + return B_ERROR; + + // Do not permit reading directories. + if (!cookie) + return EISDIR; + + *len = btRead(ns->s, &node->fhandle, pos, *len, buf); + + return B_OK; +} + +extern int fs_write(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, const void *buf, size_t *len) +{ + // Do not permit writing directories. + if (!cookie) + return EISDIR; + + if (cookie->omode & O_APPEND) + pos += cookie->original_size; + + *len = btWrite(ns->s, &node->fhandle, pos, *len, buf); + btStat(ns->s, &node->fhandle, &cookie->st); + + return B_OK; +} + +extern int fs_wstat(fs_nspace *ns, fs_node *node, struct stat *st, long mask) +{ + int error = btWStat(ns->s, &node->fhandle, st, mask); + if (error != B_OK) + return error; + + return notify_listener(B_STAT_CHANGED, ns->nsid, 0, 0, node->vnid, NULL); +} + +extern int fs_wfsstat(fs_nspace *ns, struct fs_info *info, long mask) +{ + return B_OK; +} + +extern int fs_create(fs_nspace *ns, fs_node *dir, const char *name, int omode, int perms, vnode_id *vnid, + fs_file_cookie **cookie) +{ + btFileHandle fhandle; + struct stat st; + status_t result; + int error; + + result = btLookup(ns->s, &dir->fhandle, name, &fhandle, &st); + + if (result == B_OK) + { + void *dummy; + fs_node *newNode = (fs_node *) malloc(sizeof(fs_node)); + newNode->fhandle = fhandle; + newNode->vnid = st.st_ino; + insert_node(ns, newNode); + + *vnid = st.st_ino; + + if ((result = get_vnode(ns->nsid, *vnid, &dummy)) < B_OK) + return result; + + if (S_ISDIR(st.st_mode)) + return EISDIR; + + if (omode & O_EXCL) + return EEXIST; + + if (omode & O_TRUNC) + if ((result = btTruncate(ns->s, &fhandle, 0L)) < B_OK) + return result; + + *cookie = (fs_file_cookie *) malloc(sizeof(fs_file_cookie)); + (*cookie)->omode = omode; + (*cookie)->original_size = st.st_size; + (*cookie)->st = st; + + return B_OK; + } + else if (result != ENOENT) + return result; + else + { + uint8 *replyBuf; + int32 status; + fs_node *newNode; + + // If the file doesn't exist, it may have previously and another user has + // deleted it. If so, our vnode layer will still have the old vnid registered + // and will panic when it gets a new one. Let's make sure the old one, if + // any, is unregistered. + + if (!(omode & O_CREAT)) + return ENOENT; + + error = btCreate(ns->s, &dir->fhandle, name, &fhandle, omode, perms, &st); + if (error != B_OK) + return error; + + newNode = (fs_node *) malloc(sizeof(fs_node)); + newNode->fhandle = fhandle; + newNode->vnid = st.st_ino; + insert_node(ns, newNode); + + *vnid = st.st_ino; + *cookie = (fs_file_cookie *) malloc(sizeof(fs_file_cookie)); + (*cookie)->omode = omode; + (*cookie)->original_size = st.st_size; + (*cookie)->st = st; + + result = new_vnode(ns->nsid, *vnid, newNode); + if (result < B_OK) + return result; + + return notify_listener(B_ENTRY_CREATED, ns->nsid, dir->vnid, 0, *vnid, name); + } +} + +extern int fs_unlink(fs_nspace *ns, fs_node *dir, const char *name) +{ + fs_node *newNode; + fs_node *dummy; + struct stat st; + btFileHandle fhandle; + int error; + + error = btLookup(ns->s, &dir->fhandle, name, &fhandle, &st); + if (error != B_OK) + return error; + + newNode = (fs_node *) malloc(sizeof(fs_node)); + newNode->fhandle = fhandle; + newNode->vnid = st.st_ino; + insert_node(ns, newNode); + + error = get_vnode(ns->nsid, st.st_ino, (void **) &dummy); + if (error != B_OK) + return error; + + if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) + return EISDIR; + + error = remove_vnode(ns->nsid, st.st_ino); + if (error != B_OK) + return error; + + error = put_vnode(ns->nsid, st.st_ino); + if (error != B_OK) + return error; + + error = btUnlink(ns->s, &dir->fhandle, name); + if (error != B_OK) + return error; + + return notify_listener(B_ENTRY_REMOVED, ns->nsid, dir->vnid, 0, st.st_ino, name); +} + +extern int fs_remove_vnode(fs_nspace *ns, fs_node *node, char r) +{ + remove_node(ns, node->vnid); + return B_OK; +} + +// fs_secure_vnode() +// +// Description: Given a node, this function determines whether the user has the +// required permission to access it. This is currently unimplemented in BFS, and +// we consequently dismiss it here as well. +// +extern int fs_secure_vnode(fs_nspace *ns, fs_node *node) +{ + return B_OK; +} + +extern int fs_mkdir(fs_nspace *ns, fs_node *dir, const char *name, int perms) +{ + btFileHandle dhandle, fhandle; + fs_node *newNode; + struct stat st; + int error; + + error = btLookup(ns->s, &dir->fhandle, name, &dhandle, &st); + if (error == B_OK) + { + void *dummy; + error = get_vnode(ns->nsid, st.st_ino, &dummy); + if (error != B_OK) + return error; + + return EEXIST; + } + else if (error != ENOENT) + return error; + + error = btCreateDir(ns->s, &dir->fhandle, name, perms | S_IFDIR, &fhandle, &st); + if (error != B_OK) + return error; + + newNode = (fs_node *) malloc(sizeof(fs_node)); + newNode->fhandle = fhandle; + newNode->vnid = st.st_ino; + insert_node(ns, newNode); + + return notify_listener(B_ENTRY_CREATED, ns->nsid, dir->vnid, 0, st.st_ino, name); +} + +extern int fs_rename(fs_nspace *ns, fs_node *olddir, const char *oldname, fs_node *newdir, const char *newname) +{ + btFileHandle fhandle; + struct stat st; + int error; + + error = btLookup(ns->s, &newdir->fhandle, newname, &fhandle, &st); + if (error == B_OK) + { + if (S_ISREG(st.st_mode)) + error = fs_unlink(ns, newdir, newname); + else + error = fs_rmdir(ns, newdir, newname); + + if (error != B_OK) + return error; + } + + error = btLookup(ns->s, &olddir->fhandle, oldname, &fhandle, &st); + if (error != B_OK) + return error; + + error = btRename(ns->s, &olddir->fhandle, oldname, &newdir->fhandle, newname); + if (error != B_OK) + return error; + + return notify_listener(B_ENTRY_MOVED, ns->nsid, olddir->vnid, newdir->vnid, st.st_ino, newname); +} + +extern int fs_rmdir(fs_nspace *ns, fs_node *dir, const char *name) +{ + fs_node *newNode; + fs_node *dummy; + btFileHandle fhandle; + struct stat st; + int error; + + error = btLookup(ns->s, &dir->fhandle, name, &fhandle, &st); + if (error != B_OK) + return error; + + newNode = (fs_node *) malloc(sizeof(fs_node)); + newNode->fhandle = fhandle; + newNode->vnid = st.st_ino; + insert_node(ns, newNode); + + error = get_vnode(ns->nsid, st.st_ino, (void **) &dummy); + if (error != B_OK) + return error; + + if (!S_ISDIR(st.st_mode)) + return ENOTDIR; + + error = remove_vnode(ns->nsid, st.st_ino); + if (error != B_OK) + return error; + + error = put_vnode(ns->nsid, st.st_ino); + if (error != B_OK) + return error; + + error = btDeleteDir(ns->s, &dir->fhandle, name); + if (error != B_OK) + return error; + + return notify_listener(B_ENTRY_REMOVED, ns->nsid, dir->vnid, 0, st.st_ino, name); +} + +extern int fs_readlink(fs_nspace *ns, fs_node *node, char *buf, size_t *bufsize) +{ + return btReadLink(ns->s, &node->fhandle, buf, bufsize); +} + +extern int fs_symlink(fs_nspace *ns, fs_node *dir, const char *name, const char *path) +{ + btFileHandle fhandle; + fs_node *newNode; + struct stat st; + int error; + + error = btLookup(ns->s, &dir->fhandle, name, &fhandle, &st); + if (error == B_OK) + { + void *dummy; + if ((error = get_vnode(ns->nsid, st.st_ino, &dummy)) < B_OK) + return error; + + return EEXIST; + } + else if (error != ENOENT) + return error; + + error = btSymLink(ns->s, &dir->fhandle, name, path); + if (error != B_OK) + return error; + + error = btLookup(ns->s, &dir->fhandle, name, &fhandle, &st); + if (error != B_OK) + return error; + + newNode = (fs_node *) malloc(sizeof(fs_node)); + newNode->fhandle = fhandle; + newNode->vnid = st.st_ino; + insert_node(ns, newNode); + + error = notify_listener(B_ENTRY_CREATED, ns->nsid, dir->vnid, 0, st.st_ino, name); + return error; +} + +// fs_access() +// +// Description: This function implements the access() system call. +// +int fs_access(void *ns, void *node, int mode) +{ + return B_OK; +} + +int fs_read_attrib(fs_nspace *ns, fs_node *node, const char *name, int type, void *buf, size_t *len, off_t pos) +{ + int bytes; + + // Automatically deny reading Tracker attributes. + if (strncmp(name, "_trk/", 5) == 0) + { + errno = B_ENTRY_NOT_FOUND; + return -1; + } + + bytes = btReadAttrib(ns->s, &node->fhandle, name, type, buf, *len, pos); + if (bytes == -1) + return -1; + + *len = bytes; + return B_OK; +} + +int fs_write_attrib(fs_nspace *ns, fs_node *node, const char *name, int type, const void *buf, size_t *len, off_t pos) +{ + int bytes; + + // Automatically deny reading Tracker attributes. + if (strncmp(name, "_trk/", 5) == 0) + { + errno = B_ENTRY_NOT_FOUND; + return -1; + } + + bytes = btWriteAttrib(ns->s, &node->fhandle, name, type, buf, *len, pos); + if (bytes == -1) + return -1; + + *len = bytes; + notify_listener(B_ATTR_CHANGED, ns->nsid, 0, 0, node->vnid, NULL); + return B_OK; +} + +// fs_open_attribdir() +// +extern int fs_open_attribdir(fs_nspace *ns, fs_node *node, btCookie **cookie) +{ + struct stat st; + int error; + + // Do a basic stat() on this file to verify we indeed have a valid file. + // If we cannot obtain this information, we have an even bigger problem. + if ((error = btStat(ns->s, &node->fhandle, &st)) < B_OK) + return error; + + // Allocate and initialize the cookie. + *cookie = (btCookie *) malloc(sizeof(btCookie)); + if (!*cookie) + return ENOMEM; + + memset((*cookie)->opaque, 0, BT_COOKIE_SIZE); + (*cookie)->lpbCache = false; + (*cookie)->eof = false; + + return B_OK; +} + +// fs_close_attribdir() +// +extern int fs_close_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie) +{ + btEmptyLPBCache(cookie); + return B_OK; +} + +// fs_rewind_attribdir() +// +extern int fs_rewind_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie) +{ + if (cookie) + { + memset(cookie->opaque, 0, BT_COOKIE_SIZE); + btEmptyLPBCache(cookie); + cookie->eof = false; + } + + return B_OK; +} + +extern int fs_read_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize) +{ + status_t result; + char *attrName; + long max; + + max = *num; + *num = 0; + + // Cause the directory to be read. + while ((result = btReadAttribDir(ns->s, &node->fhandle, &attrName, cookie)) == B_OK) + { + if (strncmp(attrName, "_trk/", 5) != 0) + { + if (bufsize < 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(attrName) + 1) + return B_OK; + + buf->d_dev = 0; + buf->d_pdev = 0; + buf->d_ino = 0; + buf->d_pino = 0; + buf->d_reclen = 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(attrName) + 1; + strcpy(buf->d_name, attrName); + + bufsize -= buf->d_reclen; + buf = (struct dirent *)((char *) buf + buf->d_reclen); + + (*num)++; + } + + free(attrName); + + if (*num == max) + return B_OK; + } + + return B_OK; +} + +// fs_free_attribdircookie() +// +extern int fs_free_attribdircookie(fs_nspace *ns, btCookie *cookie) +{ +// if (cookie) +// { +// btEmptyLPBCache(cookie); +// free(cookie); +// } + + return B_OK; +} + +// fs_remove_attrib() +// +extern int fs_remove_attrib(fs_nspace *ns, fs_node *node, const char *name) +{ + // Automatically deny removing Tracker attributes. + if (strncmp(name, "_trk/", 5) == 0) + { + errno = B_ENTRY_NOT_FOUND; + return -1; + } + + return btRemoveAttrib(ns->s, &node->fhandle, name); +} + +// fs_stat_attrib() +// +extern int fs_stat_attrib(fs_nspace *ns, fs_node *node, const char *name, struct attr_info *buf) +{ + buf->type = 0; + buf->size = 0; + + // Automatically deny reading Tracker attributes. + if (strncmp(name, "_trk/", 5) == 0) + { + errno = B_ENTRY_NOT_FOUND; + return -1; + } + + return btStatAttrib(ns->s, &node->fhandle, name, buf); +} + +// fs_open_indexdir() +// +extern int fs_open_indexdir(fs_nspace *ns, btCookie **cookie) +{ + // Allocate and initialize the cookie. + *cookie = (btCookie *) malloc(sizeof(btCookie)); + memset ((*cookie)->opaque, 0, BT_COOKIE_SIZE); + (*cookie)->eof = false; + + return B_OK; +} + +// fs_close_indexdir() +// +extern int fs_close_indexdir(fs_nspace *ns, btCookie *cookie) +{ + return B_OK; +} + +// fs_rewind_indexdir() +// +extern int fs_rewind_indexdir(fs_nspace *ns, btCookie *cookie) +{ + memset(cookie->opaque, 0, BT_COOKIE_SIZE); + cookie->eof = false; + return B_OK; +} + +// fs_read_indexdir() +// +extern int fs_read_indexdir(fs_nspace *ns, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize) +{ + status_t result; + char indexName[100]; + long max; + + max = *num; + *num = 0; + + // Cause the directory to be read. + while ((result = btReadIndexDir(ns->s, indexName, sizeof(indexName) - 1, cookie)) == B_OK) + { + if (bufsize < 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(indexName) + 1) + return B_OK; + + buf->d_dev = 0; + buf->d_pdev = 0; + buf->d_ino = 0; + buf->d_pino = 0; + buf->d_reclen = 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(indexName) + 1; + strcpy(buf->d_name, indexName); + + bufsize -= buf->d_reclen; + buf = (struct dirent *)((char *) buf + buf->d_reclen); + + (*num)++; + + if (*num == max) + return B_OK; + } + + return B_OK; +} + +// fs_free_indexdircookie() +// +extern int fs_free_indexdircookie(fs_nspace *ns, btCookie *cookie) +{ + if (cookie) + free(cookie); + + return B_OK; +} + +extern int fsCreateIndex(fs_nspace *ns, const char *name, int type, int flags) +{ + return btCreateIndex(ns->s, name, type, flags); +} + +extern int fsRemoveIndex(fs_nspace *ns, const char *name) +{ + return btRemoveIndex(ns->s, name); +} + +extern int fsStatIndex(fs_nspace *ns, const char *name, struct index_info *buf) +{ + buf->type = 0; + buf->size = 0; + buf->modification_time = 0; + buf->creation_time = 0; + buf->uid = 0; + buf->gid = 0; + + return btStatIndex(ns->s, name, buf); +} + +extern int fsOpenQuery(fs_nspace *ns, const char *query, ulong flags, port_id port, long token, btQueryCookie **cookie) +{ + // Allocate and initialize the cookie. + *cookie = (btQueryCookie *) malloc(sizeof(btQueryCookie)); + memset ((*cookie)->opaque, 0, BT_COOKIE_SIZE); + (*cookie)->query = strdup(query); + + return B_OK; +} + +extern int fsCloseQuery(fs_nspace *ns, btQueryCookie *cookie) +{ + return B_OK; +} + +extern int fsReadQuery(fs_nspace *ns, btQueryCookie *cookie, long *num, struct dirent *buf, size_t bufsize) +{ + char *filename; + vnode_id vnid; + long max, bufContent; + + max = *num; + *num = 0; + + while (btReadQuery(ns->s, &filename, &vnid, cookie) == B_OK) + { + bufContent = 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(filename) + 1; + if (bufsize < bufContent) + return B_OK; + + buf->d_dev = ns->nsid; + buf->d_pdev = ns->nsid; + buf->d_ino = vnid; + buf->d_pino = vnid; + buf->d_reclen = bufContent; + strcpy(buf->d_name, filename); + + bufsize -= bufContent; + buf = (struct dirent *)((char *) buf + bufContent); + + free(filename); + + (*num)++; + if (*num == max) + return B_OK; + } + + return B_OK; +} + +extern int fsFreeQueryCookie(fs_nspace *ns, btQueryCookie *cookie) +{ + if (cookie) + { + if (cookie->query) + free(cookie->query); + + free(cookie); + } + + return B_OK; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/nfs_add_on.h b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/nfs_add_on.h new file mode 100644 index 0000000000..34108a6f00 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/backups/nfs_add_on.h @@ -0,0 +1,140 @@ +#ifndef _NFS_ADD_ON_H +#define _NFS_ADD_ON_H + +#include "fsproto.h" +#include "betalk.h" + +#include +#include +#include + +struct mount_bt_params +{ + unsigned int serverIP; + char *server; + char *export; + uid_t uid; + gid_t gid; + char *hostname; +}; + +struct fs_node +{ + vnode_id vnid; + struct btFileHandle fhandle; + struct fs_node *next; +}; + +struct fs_nspace +{ + nspace_id nsid; + + thread_id tid; + bool quit; + int s; + + struct sockaddr_in mountAddr,nfsAddr; + + int32 xid; + + vnode_id rootid; + + sem_id sem; + struct fs_node *first; + + struct mount_bt_params params; +}; + +struct fs_file_cookie +{ + int omode; + off_t original_size; + struct stat st; +}; + +typedef struct fs_nspace fs_nspace; +typedef struct fs_node fs_node; +typedef struct fs_file_cookie fs_file_cookie; + +int fs_read_vnode(fs_nspace *ns, vnode_id vnid, char r, fs_node **node); +int fs_write_vnode(fs_nspace *ns, fs_node *node, char r); + +int fs_walk(fs_nspace *ns, fs_node *base, const char *file, char **newpath, + vnode_id *vnid); + +int fs_opendir(fs_nspace *ns, fs_node *node, btCookie **cookie); +int fs_closedir(fs_nspace *ns, fs_node *node, btCookie *cookie); +int fs_rewinddir(fs_nspace *ns, fs_node *node, btCookie *cookie); +int fs_readdir(fs_nspace *ns, fs_node *node, btCookie *cookie, long *num, + struct dirent *buf, size_t bufsize); + +int fs_free_dircookie(fs_nspace *ns, fs_node *node, btCookie *cookie); +int fs_rstat(fs_nspace *ns, fs_node *node, struct stat *); +int fs_mount(nspace_id nsid, const char *devname, ulong flags, + struct mount_bt_params *parms, size_t len, fs_nspace **data, vnode_id *vnid); +int fs_unmount(fs_nspace *ns); +int fs_rfsstat(fs_nspace *ns, struct fs_info *); + +int fs_open(fs_nspace *ns, fs_node *node, int omode, fs_file_cookie **cookie); +int fs_close(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie); +int fs_free_cookie(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie); +int fs_read(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, void *buf, + size_t *len); + +int fs_write(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, + const void *buf, size_t *len); + +int fs_wstat(fs_nspace *ns, fs_node *node, struct stat *, long mask); +int fs_wfsstat(fs_nspace *ns, struct fs_info *, long mask); +int fs_create(fs_nspace *ns, fs_node *dir, const char *name, + int omode, int perms, vnode_id *vnid, fs_file_cookie **cookie); + +int fs_unlink(fs_nspace *ns, fs_node *dir, const char *name); +int fs_remove_vnode(fs_nspace *ns, fs_node *node, char r); +int fs_secure_vnode(fs_nspace *ns, fs_node *node); + +int fs_mkdir(fs_nspace *ns, fs_node *dir, const char *name, int perms); + +int fs_rename(fs_nspace *ns, fs_node *olddir, const char *oldname, + fs_node *newdir, const char *newname); + +int fs_rmdir(fs_nspace *ns, fs_node *dir, const char *name); +int fs_readlink(fs_nspace *ns, fs_node *node, char *buf, size_t *bufsize); + +int fs_symlink(fs_nspace *ns, fs_node *dir, const char *name, + const char *path); + +btFileHandle handle_from_vnid (fs_nspace *ns, vnode_id vnid); + +extern status_t bt_getattr(fs_nspace *ns, const btFileHandle *fhandle, struct stat *st); +extern void insert_node(fs_nspace *ns, fs_node *node); +extern void remove_node(fs_nspace *ns, vnode_id vnid); + +extern int fs_access(void *ns, void *node, int mode); + +extern int fs_read_attrib(fs_nspace *ns, fs_node *node, const char *name, int type, void *buf, size_t *len, off_t pos); +extern int fs_write_attrib(fs_nspace *ns, fs_node *node, const char *name, int type, const void *buf, size_t *len, off_t pos); +extern int fs_open_attribdir(fs_nspace *ns, fs_node *node, btCookie **cookie); +extern int fs_close_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie); +extern int fs_rewind_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie); +extern int fs_read_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize); +extern int fs_remove_attrib(fs_nspace *ns, fs_node *node, const char *name); +extern int fs_stat_attrib(fs_nspace *ns, fs_node *node, const char *name, struct attr_info *buf); + +extern int fs_open_indexdir(fs_nspace *ns, btCookie **cookie); +extern int fs_close_indexdir(fs_nspace *ns, btCookie *cookie); +extern int fs_rewind_indexdir(fs_nspace *ns, btCookie *cookie); +extern int fs_read_indexdir(fs_nspace *ns, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize); +extern int fs_free_indexdircookie(fs_nspace *ns, btCookie *cookie); +extern int fsCreateIndex(fs_nspace *ns, const char *name, int type, int flags); +extern int fsRemoveIndex(fs_nspace *ns, const char *name); +extern int fsStatIndex(fs_nspace *ns, const char *name, struct index_info *buf); + +enum +{ + C_ERROR_STALE=B_ERRORS_END+1 +}; + +#define USE_SYSTEM_AUTHENTICATION 1 + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/betalk.h new file mode 100644 index 0000000000..af38d0d926 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +// The different types of network resources supported by BeServed. +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRITNER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 32768 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 128 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int nsid; + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +typedef struct rpcInfo +{ + thread_id rpcThread; + int32 quitXID; + + uint32 serverIP; + int32 serverPort; + int s; +} bt_rpcinfo; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket inPacket; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/btClient.c b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/btClient.c new file mode 100644 index 0000000000..a6f9177e07 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/btClient.c @@ -0,0 +1,1874 @@ +// LDAPAdd.cpp : Defines the entry point for the console application. +// + +#include "betalk.h" + +#include "netdb.h" +#include "nfs_add_on.h" +#include "sysdepdefs.h" + +#ifndef BONE_VERSION +#include "ksocket.h" +#else +#include +extern struct bone_socket_info *bone_module; +#endif + +#define BT_RPC_THREAD_NAME "BeServed RPC Marshaller" +#define BT_MAX_TOTAL_ATTEMPTS 4 +#define BT_ATTEMPTS_BEFORE_RESTART 2 + + +int btConnect(fs_nspace *ns, unsigned int serverIP, int port); +void btDisconnect(fs_nspace *ns); +bool btGetAuthentication(fs_nspace *ns); +bool btReconnect(fs_nspace *ns); +int32 btRPCReceive(void *data); +void btRPCInit(fs_nspace *ns); +void btRPCClose(fs_nspace *ns); + +int btRecv(int sock, void *data, int dataLen, int flags); + +void btRPCRecordCall(bt_rpccall *call); +void btRPCRemoveCall(bt_rpccall *call); +void btRPCFreeCall(bt_rpccall *call); +void btCreateInPacket(bt_rpccall *call, char *buffer, unsigned int length); +void btDestroyInPacket(bt_inPacket *packet); +bt_rpccall *btRPCInvoke(fs_nspace *ns, bt_outPacket *packet, bool lastPkt, bool burst); + +int btMount(fs_nspace *ns, char *shareName, char *user, char *password, vnode_id *vnid); +int btLookup(fs_nspace *ns, vnode_id dir_vnid, char *file, vnode_id *file_vnid, struct stat *st); +int btStat(fs_nspace *ns, vnode_id vnid, struct stat *st); +int btGetFSInfo(fs_nspace *ns, vnode_id vnid, bt_fsinfo *fsinfo); +int btReadDir(fs_nspace *ns, vnode_id dir_vnid, vnode_id *file_vnid, char **filename, btCookie *cookie); +size_t btRead(fs_nspace *ns, vnode_id vnid, off_t pos, size_t len, char *buf); +int btCreate(fs_nspace *ns, vnode_id dir_vnid, char *name, vnode_id *file_vnid, int omode, int perms, struct stat *st); +int btTruncate(fs_nspace *ns, vnode_id vnid, int64 len); +int btUnlink(fs_nspace *ns, vnode_id vnid, char *name); +int btCreateDir(fs_nspace *ns, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, struct stat *st); +int btRename(fs_nspace *ns, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName); +int btDeleteDir(fs_nspace *ns, vnode_id vnid, char *name); +int btReadLink(fs_nspace *ns, vnode_id vnid, char *buf, size_t *bufsize); +int btSymLink(fs_nspace *ns, vnode_id vnid, char *name, char *path); +int btReadAttrib(fs_nspace *ns, vnode_id vnid, char *name, int type, void *buffer, size_t len, off_t pos); +int btWriteAttrib(fs_nspace *ns, vnode_id vnid, char *name, int type, void *buffer, size_t len, off_t pos); +int btReadAttribDir(fs_nspace *ns, vnode_id vnid, char **attrName, btCookie *cookie); +int btRemoveAttrib(fs_nspace *ns, vnode_id vnid, char *name); +int btStatAttrib(fs_nspace *ns, vnode_id vnid, char *name, struct attr_info *info); +int btReadIndexDir(fs_nspace *ns, char **indexName, int bufLength, btCookie *cookie); +int btCreateIndex(fs_nspace *ns, char *name, int type, int flags); +int btRemoveIndex(fs_nspace *ns, char *name); +int btStatIndex(fs_nspace *ns, char *name, struct index_info *buf); +int btReadQuery(fs_nspace *ns, char **fileName, vnode_id *vnid, vnode_id *parent, btQueryCookie *cookie); +int btCommit(fs_nspace *ns, vnode_id vnid); + +// DNLC Routines +void AddDNLCEntry(fs_nspace *ns, vnode_id parent, char *name, vnode_id vnid, struct stat *st); +void DeleteDNLCEntry(fs_nspace *ns, vnode_id vnid); +void RemoveDNLCEntry(fs_nspace *ns, dnlc_entry *dnlc); +bool CheckDNLCByName(fs_nspace *ns, vnode_id parent, const char *name, vnode_id *vnid, struct stat *st); +bool CheckDNLCByVnid(fs_nspace *ns, vnode_id vnid, struct stat *st); +void PurgeDNLCEntries(fs_nspace *ns, vnode_id vnid, bool entireDir); + +bt_rpccall *rootCall = NULL; + +sem_id callSem; +sem_id connectSem; + +vint32 nextXID = 1; + + +void btRPCInit(fs_nspace *ns) +{ + ns->rpcThread = 0; + ns->quitXID = 0; + + callSem = create_sem(1, "rpcCall"); + set_sem_owner(callSem, B_SYSTEM_TEAM); + + connectSem = create_sem(1, "rpcConnection"); + set_sem_owner(connectSem, B_SYSTEM_TEAM); + + ns->rpcThread = spawn_kernel_thread(btRPCReceive, BT_RPC_THREAD_NAME, B_NORMAL_PRIORITY, ns); + resume_thread(ns->rpcThread); +} + +void btRPCClose(fs_nspace *ns) +{ + if (ns->rpcThread > 0) + { + status_t exitVal; + wait_for_thread(ns->rpcThread, &exitVal); + } + + // Close the socket used for all file system RPC communications, + // now that we know the RPC recipient thread is dead. + kclosesocket(ns->s); + + delete_sem(connectSem); + delete_sem(callSem); +} + +int btRecvMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesRead = 0; + do + { + int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags); + if (bytes == -1) + return -1; + + bytesRead += bytes; + } while (bytesRead < dataLen); + + return bytesRead; +} + +int btRecv(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = krecv(sock, data, dataLen, flags); + if (bytes == 0) + return -1; + else if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +int btSendMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesSent = 0; + do + { + int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags); + if (bytes == -1) + return -1; + + bytesSent += bytes; + } while (bytesSent < dataLen); + + return bytesSent; +} + +int btSend(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = ksend(sock, data, dataLen, flags); + if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +int32 btRPCReceive(void *data) +{ + fs_nspace *ns = (fs_nspace *) data; + bt_rpccall *call; + char signature[20], *buffer; + int32 xid, nsid, length, sigLen; + int sock = ns->s; + int bytes; + bool failure = false; + +#ifdef BONE_VERSION + fd_set sockSet; + struct timeval timeout; + + FD_ZERO(&sockSet); + timeout.tv_sec = 30; + timeout.tv_usec = 0; +#endif + + while (!failure) + { +#ifdef BONE_VERSION + FD_SET(sock, &sockSet); + select(sock + 1, &sockSet, NULL, NULL, &timeout); + + if (FD_ISSET(sock, &sockSet)) + { +#endif + + // Receive the signature. If a socket error occurs, break out of the loop and + // effectively exit this thread because the socket is closed. + sigLen = strlen(BT_RPC_SIGNATURE); + memset(signature, 0, sigLen); + if (btRecvMsg(sock, signature, sigLen, 0) == -1) + break; + + // Make sure the signature is correct. Otherwise, ignore it and start over. + signature[sigLen] = 0; + if (strcmp(signature, BT_RPC_SIGNATURE)) + continue; + + // Now read the transaction id (XID) and the length of the packet body. + bytes = btRecvMsg(sock, &xid, sizeof(int32), 0); + if (bytes > 0) + bytes = btRecvMsg(sock, &length, sizeof(int32), 0); + + xid = B_LENDIAN_TO_HOST_INT32(xid); + length = B_LENDIAN_TO_HOST_INT32(length); + if (length <= 0 || length >= BT_RPC_MAX_PACKET_SIZE) + continue; + + buffer = (char *) malloc(length + 1); + if (!buffer) + continue; + + // Read the remainder of the packet. + if (btRecvMsg(sock, buffer, length, 0) == -1) + failure = true; + + buffer[length] = 0; + + while (acquire_sem(callSem) == B_INTERRUPTED); + + call = rootCall; + while (call) + { + if (call->xid == xid) + { + btCreateInPacket(call, buffer, length); + release_sem(call->sem); + break; + } + + call = call->next; + } + + release_sem(callSem); + + // The originating RPC call was not found. This is probably not a very + // good sign. + if (!call) + free(buffer); + + // If a valid quit XID has been defined, and it's equal to the current + // XID, quit. + if (ns->quitXID) + if (ns->quitXID == xid) + break; + +#ifdef BONE_VERSION + } +#endif + + } +} + +void btCreateInPacket(bt_rpccall *call, char *buffer, unsigned int length) +{ + bt_inPacket *packet; + + packet = (bt_inPacket *) malloc(sizeof(bt_inPacket)); + if (!packet) + return; + + packet->buffer = buffer; + packet->length = length; + packet->offset = 0; + + call->inPacket = packet; +} + +void btDestroyInPacket(bt_inPacket *packet) +{ + if (packet) + { + if (packet->buffer) + free(packet->buffer); + + free(packet); + } +} + +void btRPCRecordCall(bt_rpccall *call) +{ + while (acquire_sem(callSem) == B_INTERRUPTED); + + call->next = rootCall; + call->prev = NULL; + if (rootCall) + rootCall->prev = call; + + rootCall = call; + + release_sem(callSem); +} + +// btRPCRemoveCall() +// +void btRPCRemoveCall(bt_rpccall *call) +{ + if (call) + { + if (call->sem > 0) + delete_sem(call->sem); + + while (acquire_sem(callSem) == B_INTERRUPTED); + + // Make this entry's predecessor point to its successor. + if (call->prev) + call->prev->next = call->next; + + // Make this entry's successor point to its predecessor. + if (call->next) + call->next->prev = call->prev; + + // If we just deleted the root node of the list, then the next node + // has become the root. + if (call == rootCall) + rootCall = call->next; + + release_sem(callSem); + + // Now we can release the memory allocated for this packet. + btDestroyInPacket(call->inPacket); + free(call); + } +} + +// btConnect() +// +int btConnect(fs_nspace *ns, unsigned int serverIP, int port) +{ + struct sockaddr_in serverAddr; + int session, addrLen, flags; + + ns->serverIP = serverIP; + ns->serverPort = port; + + // Store the length of the socket addressing structure for accept(). + addrLen = sizeof(struct sockaddr_in); + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(port); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(serverIP); + + // Create a new socket to receive incoming requests. + session = ksocket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (session == INVALID_SOCKET) + return INVALID_SOCKET; + + // Bind that socket to the address constructed above. + if (kconnect(session, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return INVALID_SOCKET; + + // Enabled periodic keep-alive messages, so we stay connected during times of + // no activity. This isn't supported by ksocketd, only in BONE. :-( +#ifdef BONE_VERSION + flags = 1; + ksetsockopt(session, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags)); +#endif + + return session; +} + +void btDisconnect(fs_nspace *ns) +{ + bt_outPacket *packet; + bt_rpccall *call; + + packet = btRPCPutHeader(BT_CMD_QUIT, 0, 0); + call = btRPCInvoke(ns, packet, true, false); + if (call) + btRPCRemoveCall(call); +} + +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length) +{ + bt_outPacket *packet; + + packet = (bt_outPacket *) malloc(sizeof(bt_outPacket)); + if (!packet) + return NULL; + + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + { + free(packet); + return NULL; + } + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + +// btRPCPutChar(packet, BT_RPC_VERSION_HI); +// btRPCPutChar(packet, BT_RPC_VERSION_LO); + btRPCPutInt32(packet, 7 + (8 * argc) + length); + btRPCPutChar(packet, command); + btRPCPutChar(packet, argc); + + return packet; +} + +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length) +{ + btRPCPutInt32(packet, type); + btRPCPutInt32(packet, length); + btRPCPutBinary(packet, data, length); +} + +bt_rpccall *btRPCInvoke(fs_nspace *ns, bt_outPacket *packet, bool lastPkt, bool burst) +{ + status_t result; + bt_rpccall *call; + int attempts; + bool failure; + + call = (bt_rpccall *) malloc(sizeof(bt_rpccall)); + if (!call) + return NULL; + + attempts = 0; + call->inPacket = NULL; + call->xid = atomic_add(&nextXID, 1); + + if (!burst) + { + if ((call->sem = create_sem(0, "rpc call")) < B_OK) + { + free(call); + return NULL; + } + + set_sem_owner(call->sem, B_SYSTEM_TEAM); + btRPCRecordCall(call); + } + + btRPCPutInt32(packet, call->xid); + btRPCPutChar(packet, BT_CMD_TERMINATOR); + + // If this is the last RPC packet that will be transmitted, store + // its XID so the RPC recipient thread will know when to quit. + if (lastPkt) + ns->quitXID = call->xid; + +doSend: + failure = false; + if (btSendMsg(ns->s, packet->buffer, packet->length, 0) == -1) + failure = true; + + if (!burst) + { + if (!failure) + do + { + result = acquire_sem_etc(call->sem, 1, B_RELATIVE_TIMEOUT, 2500000); + } + while (result == B_INTERRUPTED); + + if (failure || result == B_TIMED_OUT) + { + dprintf("RPC call timed out\n"); + attempts++; + if (attempts >= BT_MAX_TOTAL_ATTEMPTS) + { + free(packet->buffer); + free(packet); + btRPCRemoveCall(call); + return NULL; + } + else if (attempts == BT_ATTEMPTS_BEFORE_RESTART) + btReconnect(ns); + + goto doSend; + } + } + + free(packet->buffer); + free(packet); + return call; +} + +bool btReconnect(fs_nspace *ns) +{ + static int counter = 0; + int curCount = counter; + bool connected = true; + + while (acquire_sem(connectSem) == B_INTERRUPTED); + + if (curCount == counter) + { + connected = false; + + kclosesocket(ns->s); + if (ns->rpcThread > 0) + kill_thread(ns->rpcThread); + + ns->s = btConnect(ns, ns->serverIP, ns->serverPort); + if (ns->s != INVALID_SOCKET) + { + ns->rpcThread = spawn_kernel_thread(btRPCReceive, BT_RPC_THREAD_NAME, B_NORMAL_PRIORITY, ns); + resume_thread(ns->rpcThread); + connected = true; + } + + counter++; + } + + release_sem(connectSem); + return connected; +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (!bytes) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + memcpy(str, &packet->buffer[packet->offset], bytes); + str[bytes] = 0; + + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return 0; + + bytes = B_LENDIAN_TO_HOST_INT64(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (!bytes) + return 0L; + + if (length < bytes) + return ERANGE; + + memcpy(buffer, &packet->buffer[packet->offset], bytes); + packet->offset += bytes; + return bytes; +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +int btRPCGetStat(bt_inPacket *packet, struct stat *st) +{ + st->st_dev = 0; + st->st_nlink = btRPCGetInt32(packet); + st->st_uid = btRPCGetInt32(packet); + st->st_gid = btRPCGetInt32(packet); + st->st_size = btRPCGetInt64(packet); + st->st_blksize = btRPCGetInt32(packet); + st->st_rdev = btRPCGetInt32(packet); + st->st_ino = btRPCGetInt64(packet); + st->st_mode = btRPCGetInt32(packet); + st->st_atime = btRPCGetInt32(packet); + st->st_mtime = btRPCGetInt32(packet); + st->st_ctime = btRPCGetInt32(packet); +} + +void btRPCPutStat(bt_outPacket *packet, struct stat *st) +{ + if (packet && st) + { + btRPCPutInt32(packet, (int) st->st_nlink); + btRPCPutInt32(packet, (int) st->st_uid); + btRPCPutInt32(packet, (int) st->st_gid); + btRPCPutInt64(packet, (int64) st->st_size); + btRPCPutInt32(packet, (int) st->st_blksize); + btRPCPutInt32(packet, (int) st->st_rdev); + btRPCPutInt64(packet, (int64) st->st_ino); + btRPCPutInt32(packet, (int) st->st_mode); + btRPCPutInt32(packet, (int) st->st_atime); + btRPCPutInt32(packet, (int) st->st_mtime); + btRPCPutInt32(packet, (int) st->st_ctime); + } +} + +void btEmptyLPBCache(btCookie *cookie) +{ + if (cookie->lpbCache) + { + cookie->lpbCache = false; + if (cookie->inPacket.buffer) + { + free(cookie->inPacket.buffer); + cookie->inPacket.buffer = NULL; + } + } +} + +// btMount() +// +int btMount(fs_nspace *ns, char *shareName, char *user, char *password, vnode_id *vnid) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_MOUNT, 3, strlen(shareName) + strlen(user) + BT_AUTH_TOKEN_LENGTH); + btRPCPutArg(outPacket, B_STRING_TYPE, shareName, strlen(shareName)); + btRPCPutArg(outPacket, B_STRING_TYPE, user, strlen(user)); + btRPCPutArg(outPacket, B_STRING_TYPE, password, BT_AUTH_TOKEN_LENGTH); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + *vnid = btRPCGetInt64(inPacket); + } + + btRPCRemoveCall(call); + } + + return error; +} + +// btLookup() +// +int btLookup(fs_nspace *ns, vnode_id dir_vnid, char *file, vnode_id *file_vnid, struct stat *st) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + if (CheckDNLCByName(ns, dir_vnid, file, file_vnid, st)) + return B_OK; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_LOOKUP, 2, 8 + strlen(file)); + btRPCPutArg(outPacket, B_INT64_TYPE, &dir_vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, file, strlen(file)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *file_vnid = btRPCGetInt64(inPacket); + btRPCGetStat(inPacket, st); + AddDNLCEntry(ns, dir_vnid, file, *file_vnid, st); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +// btStat() +// +int btStat(fs_nspace *ns, vnode_id vnid, struct stat *st) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + if (CheckDNLCByVnid(ns, vnid, st)) + return B_OK; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_STAT, 1, 8); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + btRPCGetStat(inPacket, st); + } + + btRPCRemoveCall(call); + } + + return error; +} + +// btGetFSInfo() +// +int btGetFSInfo(fs_nspace *ns, vnode_id vnid, bt_fsinfo *fsinfo) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_FSINFO, 1, 8); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + fsinfo->blockSize = btRPCGetInt32(inPacket); + fsinfo->totalBlocks = btRPCGetInt32(inPacket); + fsinfo->freeBlocks = btRPCGetInt32(inPacket); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +// btReadDir() +// +int btReadDir(fs_nspace *ns, vnode_id dir_vnid, vnode_id *file_vnid, char **filename, btCookie *cookie) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + struct stat st; + char *mimeType; + int error, value; + + error = EHOSTUNREACH; + call = NULL; + inPacket = NULL; + *filename = NULL; + *file_vnid = 0; + + if (cookie->eof) + return ENOENT; + + // If no entries are currently cached, construct a call to the server to + // obtain the next series of directory entries. + if (cookie->lpbCache) + { + // If we had an existing packet buffer stored, remove it now. + inPacket = &cookie->inPacket; + if (inPacket->offset >= inPacket->length) + btEmptyLPBCache(cookie); + } + + if (!cookie->lpbCache) + { + outPacket = btRPCPutHeader(BT_CMD_READDIR, 2, 8 + BT_COOKIE_SIZE); + btRPCPutArg(outPacket, B_INT64_TYPE, &dir_vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, cookie->opaque, BT_COOKIE_SIZE); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + cookie->inPacket.buffer = (char *) malloc(call->inPacket->length); + if (cookie->inPacket.buffer) + { + inPacket = &cookie->inPacket; + memcpy(inPacket->buffer, call->inPacket->buffer, call->inPacket->length); + inPacket->length = call->inPacket->length; + inPacket->offset = 0; + cookie->lpbCache = true; + } + } + } + + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *file_vnid = btRPCGetInt64(inPacket); + *filename = btRPCGetNewString(inPacket); + if (!*filename) + return ENOENT; + + value = btRPCGetInt32(inPacket); + memcpy(cookie->opaque, &value, sizeof(value)); + btRPCGetStat(inPacket, &st); + + // Now add a DNLC entry for this file. + AddDNLCEntry(ns, dir_vnid, *filename, *file_vnid, &st); + } + else + { + btEmptyLPBCache(cookie); + cookie->eof = true; + } + } + + if (call) + btRPCRemoveCall(call); + + return error; +} + +// btRead() +// +size_t btRead(fs_nspace *ns, vnode_id vnid, off_t pos, size_t len, char *buf) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + struct stat st; + size_t bytesRead, filePos; + int32 byteCount; + int error; + + error = B_OK; + bytesRead = 0; + filePos = pos; + + // Get the file size from the server and verify we're not going beyond it. + // If we're already positioned at the end of the file, there's no point in + // trying to read any further. + btStat(ns, vnid, &st); + if (filePos >= st.st_size) + return 0; + + while (filePos < st.st_size && bytesRead < len && error == B_OK) + { + byteCount = min(BT_MAX_IO_BUFFER, len - bytesRead); + + outPacket = btRPCPutHeader(BT_CMD_READ, 3, 16); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_INT32_TYPE, &filePos, sizeof(filePos)); + btRPCPutArg(outPacket, B_INT32_TYPE, &byteCount, sizeof(byteCount)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + int32 bytesRecv; + bytesRecv = btRPCGetString(inPacket, buf + bytesRead, byteCount); + bytesRead += bytesRecv; + filePos += bytesRecv; + } + } + + btRPCRemoveCall(call); + } + } + + return bytesRead; +} + +// btWrite() +// +size_t btWrite(fs_nspace *ns, vnode_id vnid, off_t pos, size_t len, char *buf) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + struct stat st; + size_t bytesWritten; + int32 byteCount, totalLen; + int error; + off_t curPos; + + bytesWritten = 0; + curPos = pos; + totalLen = (int32) len; + + while (bytesWritten < len) + { + byteCount = min(BT_MAX_IO_BUFFER, len - bytesWritten); + + outPacket = btRPCPutHeader(BT_CMD_WRITE, 5, 24 + byteCount); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_INT64_TYPE, &curPos, sizeof(curPos)); + btRPCPutArg(outPacket, B_INT32_TYPE, &byteCount, sizeof(byteCount)); + btRPCPutArg(outPacket, B_INT32_TYPE, &totalLen, sizeof(totalLen)); + btRPCPutArg(outPacket, B_STRING_TYPE, buf + bytesWritten, byteCount); + call = btRPCInvoke(ns, outPacket, false, true); + + bytesWritten += byteCount; + curPos += byteCount; + + // All subsequent calls must specify a total length of zero. + totalLen = 0; + } + + if (btCommit(ns, vnid) != B_OK) + bytesWritten = 0; + + DeleteDNLCEntry(ns, vnid); + return bytesWritten; +} + +int btCreate(fs_nspace *ns, vnode_id dir_vnid, char *name, vnode_id *file_vnid, int omode, int perms, struct stat *st) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_CREATE, 4, 8 + strlen(name) + 8); + btRPCPutArg(outPacket, B_INT64_TYPE, &dir_vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_INT32_TYPE, &omode, sizeof(omode)); + btRPCPutArg(outPacket, B_INT32_TYPE, &perms, sizeof(perms)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *file_vnid = btRPCGetInt64(inPacket); + btRPCGetStat(inPacket, st); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btTruncate(fs_nspace *ns, vnode_id vnid, int64 len) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_TRUNCATE, 2, 16); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_INT64_TYPE, &len, sizeof(len)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btUnlink(fs_nspace *ns, vnode_id vnid, char *name) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_UNLINK, 2, 8 + strlen(name)); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + PurgeDNLCEntries(ns, vnid, false); + return error; +} + +int btCreateDir(fs_nspace *ns, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, struct stat *st) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_MKDIR, 3, 8 + strlen(name) + 4); + btRPCPutArg(outPacket, B_INT64_TYPE, &dir_vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_INT32_TYPE, &perms, sizeof(perms)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *file_vnid = btRPCGetInt64(inPacket); + btRPCGetStat(inPacket, st); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btRename(fs_nspace *ns, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_RENAME, 4, 16 + strlen(oldName) + strlen(newName)); + btRPCPutArg(outPacket, B_INT64_TYPE, &old_vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, oldName, strlen(oldName)); + btRPCPutArg(outPacket, B_INT64_TYPE, &new_vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, newName, strlen(newName)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + PurgeDNLCEntries(ns, old_vnid, false); + return error; +} + +int btDeleteDir(fs_nspace *ns, vnode_id vnid, char *name) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_RMDIR, 2, 8 + strlen(name)); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + PurgeDNLCEntries(ns, vnid, true); + return error; +} + +int btReadLink(fs_nspace *ns, vnode_id vnid, char *buf, size_t *bufsize) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_READLINK, 1, 8); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + *bufsize = btRPCGetString(inPacket, buf, (int) *bufsize); + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btSymLink(fs_nspace *ns, vnode_id vnid, char *name, char *path) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_SYMLINK, 3, 8 + strlen(name) + strlen(path)); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_STRING_TYPE, path, strlen(path)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btWStat(fs_nspace *ns, vnode_id vnid, struct stat *st, long mask) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_WSTAT, 8, 36); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_INT32_TYPE, &mask, sizeof(mask)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_mode, sizeof(int32)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_uid, sizeof(int32)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_gid, sizeof(int32)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_size, sizeof(int32)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_atime, sizeof(int32)); + btRPCPutArg(outPacket, B_INT32_TYPE, &st->st_mtime, sizeof(int32)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btReadAttrib(fs_nspace *ns, vnode_id vnid, char *name, int type, void *buffer, size_t len, off_t pos) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + int32 bytesRead; + int32 newlen = (int32) len; + int32 newpos = (int32) pos; + + bytesRead = -1; + + outPacket = btRPCPutHeader(BT_CMD_READATTRIB, 5, 8 + strlen(name) + 12); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_INT32_TYPE, &type, sizeof(type)); + btRPCPutArg(outPacket, B_INT32_TYPE, &newpos, sizeof(newpos)); + btRPCPutArg(outPacket, B_INT32_TYPE, &newlen, sizeof(newlen)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + bytesRead = btRPCGetInt32(inPacket); + if (bytesRead > 0) + btRPCGetString(inPacket, (char *) buffer, len); + } + else + { + bytesRead = -1; + errno = error; + } + } + + btRPCRemoveCall(call); + } + + return bytesRead; +} + +int btWriteAttrib(fs_nspace *ns, vnode_id vnid, char *name, int type, void *buffer, size_t len, off_t pos) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + int32 bytesWritten; + int32 newlen = (int32) len; + int32 newpos = (int32) pos; + + bytesWritten = -1; + + outPacket = btRPCPutHeader(BT_CMD_WRITEATTRIB, 6, 8 + strlen(name) + len + 12); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_INT32_TYPE, &type, sizeof(type)); + btRPCPutArg(outPacket, B_STRING_TYPE, buffer, len); + btRPCPutArg(outPacket, B_INT32_TYPE, &newpos, sizeof(newpos)); + btRPCPutArg(outPacket, B_INT32_TYPE, &newlen, sizeof(newlen)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + bytesWritten = btRPCGetInt32(inPacket); + else + { + bytesWritten = -1; + errno = error; + } + } + + btRPCRemoveCall(call); + } + + return bytesWritten; +} + +int btReadAttribDir(fs_nspace *ns, vnode_id vnid, char **attrName, btCookie *cookie) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error, value; + + error = EHOSTUNREACH; + call = NULL; + inPacket = NULL; + *attrName = NULL; + + if (cookie->eof) + return ENOENT; + + // If no entries are currently cached, construct a call to the server to + // obtain the next series of directory entries. + if (cookie->lpbCache) + { + // If we had an existing packet buffer stored, remove it now. + inPacket = &cookie->inPacket; + if (inPacket->offset >= inPacket->length) + btEmptyLPBCache(cookie); + } + + if (!cookie->lpbCache) + { + outPacket = btRPCPutHeader(BT_CMD_READATTRIBDIR, 2, 8 + BT_COOKIE_SIZE); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, cookie->opaque, BT_COOKIE_SIZE); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + cookie->inPacket.buffer = (char *) malloc(call->inPacket->length); + if (cookie->inPacket.buffer) + { + inPacket = &cookie->inPacket; + memcpy(inPacket->buffer, call->inPacket->buffer, call->inPacket->length); + inPacket->length = call->inPacket->length; + inPacket->offset = 0; + cookie->lpbCache = true; + } + } + } + + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *attrName = btRPCGetNewString(inPacket); + if (!*attrName) + return ENOENT; + + value = btRPCGetInt32(inPacket); + memcpy(cookie->opaque, &value, sizeof(value)); + } + else + { + btEmptyLPBCache(cookie); + cookie->eof = true; + } + } + + if (call) + btRPCRemoveCall(call); + + return error; +} + +int btRemoveAttrib(fs_nspace *ns, vnode_id vnid, char *name) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_REMOVEATTRIB, 2, 8 + strlen(name)); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btStatAttrib(fs_nspace *ns, vnode_id vnid, char *name, struct attr_info *info) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_STATATTRIB, 2, 8 + strlen(name)); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + info->type = btRPCGetInt32(inPacket); + info->size = btRPCGetInt64(inPacket); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btReadIndexDir(fs_nspace *ns, char **indexName, int bufLength, btCookie *cookie) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error, value; + + error = EHOSTUNREACH; + *indexName = NULL; + + if (cookie->eof) + return ENOENT; + + outPacket = btRPCPutHeader(BT_CMD_READINDEXDIR, 1, BT_COOKIE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, cookie->opaque, BT_COOKIE_SIZE); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *indexName = btRPCGetNewString(inPacket); + value = btRPCGetInt32(inPacket); + memcpy(cookie->opaque, &value, sizeof(value)); + } + else + cookie->eof = true; + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btCreateIndex(fs_nspace *ns, char *name, int type, int flags) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_CREATEINDEX, 3, strlen(name) + 8); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + btRPCPutArg(outPacket, B_INT32_TYPE, &type, sizeof(type)); + btRPCPutArg(outPacket, B_INT32_TYPE, &flags, sizeof(flags)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btRemoveIndex(fs_nspace *ns, char *name) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_REMOVEINDEX, 1, strlen(name)); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +int btStatIndex(fs_nspace *ns, char *name, struct index_info *buf) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_STATINDEX, 1, strlen(name)); + btRPCPutArg(outPacket, B_STRING_TYPE, name, strlen(name)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + buf->type = btRPCGetInt32(inPacket); + buf->size = btRPCGetInt64(inPacket); + buf->modification_time = btRPCGetInt32(inPacket); + buf->creation_time = btRPCGetInt32(inPacket); + buf->uid = btRPCGetInt32(inPacket); + buf->gid = btRPCGetInt32(inPacket); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +int btReadQuery(fs_nspace *ns, char **fileName, vnode_id *vnid, vnode_id *parent, btQueryCookie *cookie) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error, value; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_READQUERY, 2, BT_COOKIE_SIZE + strlen(cookie->query)); + btRPCPutArg(outPacket, B_STRING_TYPE, cookie->opaque, BT_COOKIE_SIZE); + btRPCPutArg(outPacket, B_STRING_TYPE, cookie->query, strlen(cookie->query)); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + { + *vnid = btRPCGetInt64(inPacket); + *parent = btRPCGetInt64(inPacket); + *fileName = btRPCGetNewString(inPacket); + if (!*fileName) + error = ENOENT; + + value = btRPCGetInt32(inPacket); + memcpy(cookie->opaque, &value, sizeof(value)); + } + } + + btRPCRemoveCall(call); + } + + return error; +} + +// btCommit() +// +int btCommit(fs_nspace *ns, vnode_id vnid) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + size_t bytes; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_COMMIT, 1, 8); + btRPCPutArg(outPacket, B_INT64_TYPE, &vnid, 8); + call = btRPCInvoke(ns, outPacket, false, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +///////////////////////// + +// AddDNLCEntry() +// +void AddDNLCEntry(fs_nspace *ns, vnode_id parent, char *name, vnode_id vnid, struct stat *st) +{ + time_t curTime = time(NULL); + dnlc_entry *dnlc; + + beginWriting(&ns->dnlcData); + + // Clean expired entries from the DNLC first. + dnlc = ns->dnlcRoot; + while (dnlc) + { + int secs = S_ISDIR(dnlc->st.st_mode) ? 30 : 15; + if (curTime - dnlc->entryTime > secs) + { + dnlc_entry *ent = dnlc->next; + RemoveDNLCEntry(ns, dnlc); + dnlc = ent; + } + + if (dnlc) + dnlc = dnlc->next; + } + + // Now add the new entry. + dnlc = (dnlc_entry *) malloc(sizeof(dnlc_entry)); + if (dnlc) + { + dnlc->prev = NULL; + dnlc->next = ns->dnlcRoot; + if (ns->dnlcRoot) + ns->dnlcRoot->prev = dnlc; + + ns->dnlcRoot = dnlc; + dnlc->vnid = vnid; + dnlc->parent = parent; + strcpy(dnlc->name, name); + memcpy(&dnlc->st, st, sizeof(struct stat)); + dnlc->entryTime = time(NULL); + } + + endWriting(&ns->dnlcData); +} + +// DeleteDNLCEntry() +// +void DeleteDNLCEntry(fs_nspace *ns, vnode_id vnid) +{ + dnlc_entry *dnlc; + + beginWriting(&ns->dnlcData); + + dnlc = ns->dnlcRoot; + while (dnlc && dnlc->vnid != vnid) + dnlc = dnlc->next; + + if (dnlc) + RemoveDNLCEntry(ns, dnlc); + + endWriting(&ns->dnlcData); +} + +// RemoveDNLCEntry() +// +void RemoveDNLCEntry(fs_nspace *ns, dnlc_entry *dnlc) +{ + if (dnlc) + { + if (dnlc == ns->dnlcRoot) + ns->dnlcRoot = dnlc->next; + + if (dnlc->next) + dnlc->next->prev = dnlc->prev; + + if (dnlc->prev) + dnlc->prev->next = dnlc->next; + + free(dnlc); + } +} + +// CheckDNLCByName() +// +bool CheckDNLCByName(fs_nspace *ns, vnode_id parent, const char *name, vnode_id *vnid, struct stat *st) +{ + dnlc_entry *dnlc; + + beginReading(&ns->dnlcData); + + dnlc = ns->dnlcRoot; + while (dnlc) + { + if (dnlc && dnlc->parent == parent) + if (strcmp(dnlc->name, name) == 0) + { + *vnid = dnlc->vnid; + memcpy(st, &dnlc->st, sizeof(struct stat)); + endReading(&ns->dnlcData); + return true; + } + + if (dnlc) + dnlc = dnlc->next; + } + + endReading(&ns->dnlcData); + return false; +} + +// CheckDNLCByVnid() +// +bool CheckDNLCByVnid(fs_nspace *ns, vnode_id vnid, struct stat *st) +{ + dnlc_entry *dnlc; + + beginReading(&ns->dnlcData); + + dnlc = ns->dnlcRoot; + while (dnlc) + { + if (dnlc && dnlc->vnid == vnid) + { + memcpy(st, &dnlc->st, sizeof(struct stat)); + endReading(&ns->dnlcData); + return true; + } + + if (dnlc) + dnlc = dnlc->next; + } + + endReading(&ns->dnlcData); + return false; +} + +// PurgeDNLCEntries() +// +void PurgeDNLCEntries(fs_nspace *ns, vnode_id vnid, bool entireDir) +{ + dnlc_entry *dnlc; + + beginWriting(&ns->dnlcData); + + dnlc = ns->dnlcRoot; + while (dnlc) + { + if (vnid == dnlc->vnid || (entireDir && vnid == dnlc->parent)) + { + dnlc_entry *ent = dnlc->next; + RemoveDNLCEntry(ns, dnlc); + + // If we're not purging an entire folder, then we're obviously + // here because this is the single vnode id we're deleting. + // Now that we've done it, just exit and save time. + if (!entireDir) + break; + + dnlc = ent; + } + + if (dnlc) + dnlc = dnlc->next; + } + + endWriting(&ns->dnlcData); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/fsproto.h b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/fsproto.h new file mode 100644 index 0000000000..a6072837d5 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/fsproto.h @@ -0,0 +1,246 @@ +#ifndef _FSPROTO_H +#define _FSPROTO_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef dev_t nspace_id; +typedef ino_t vnode_id; + +/* UGLY UGLY UGLY */ +#ifndef _DRIVERS_H +struct selectsync; +typedef struct selectsync selectsync; +#endif + + +/* + * PUBLIC PART OF THE FILE SYSTEM PROTOCOL + */ + +#define WSTAT_MODE 0x0001 +#define WSTAT_UID 0x0002 +#define WSTAT_GID 0x0004 +#define WSTAT_SIZE 0x0008 +#define WSTAT_ATIME 0x0010 +#define WSTAT_MTIME 0x0020 +#define WSTAT_CRTIME 0x0040 + +#define WFSSTAT_NAME 0x0001 + +#define B_ENTRY_CREATED 1 +#define B_ENTRY_REMOVED 2 +#define B_ENTRY_MOVED 3 +#define B_STAT_CHANGED 4 +#define B_ATTR_CHANGED 5 +#define B_DEVICE_MOUNTED 6 +#define B_DEVICE_UNMOUNTED 7 + +#define B_STOP_WATCHING 0x0000 +#define B_WATCH_NAME 0x0001 +#define B_WATCH_STAT 0x0002 +#define B_WATCH_ATTR 0x0004 +#define B_WATCH_DIRECTORY 0x0008 + +#define SELECT_READ 1 +#define SELECT_WRITE 2 +#define SELECT_EXCEPTION 3 + +#define B_CUR_FS_API_VERSION 2 + +struct attr_info; +struct index_info; + +typedef int op_read_vnode(void *ns, vnode_id vnid, char r, void **node); +typedef int op_write_vnode(void *ns, void *node, char r); +typedef int op_remove_vnode(void *ns, void *node, char r); +typedef int op_secure_vnode(void *ns, void *node); + +typedef int op_walk(void *ns, void *base, const char *file, char **newpath, + vnode_id *vnid); + +typedef int op_access(void *ns, void *node, int mode); + +typedef int op_create(void *ns, void *dir, const char *name, + int omode, int perms, vnode_id *vnid, void **cookie); +typedef int op_mkdir(void *ns, void *dir, const char *name, int perms); +typedef int op_symlink(void *ns, void *dir, const char *name, + const char *path); +typedef int op_link(void *ns, void *dir, const char *name, void *node); + +typedef int op_rename(void *ns, void *olddir, const char *oldname, + void *newdir, const char *newname); +typedef int op_unlink(void *ns, void *dir, const char *name); +typedef int op_rmdir(void *ns, void *dir, const char *name); + +typedef int op_readlink(void *ns, void *node, char *buf, size_t *bufsize); + +typedef int op_opendir(void *ns, void *node, void **cookie); +typedef int op_closedir(void *ns, void *node, void *cookie); +typedef int op_rewinddir(void *ns, void *node, void *cookie); +typedef int op_readdir(void *ns, void *node, void *cookie, long *num, + struct dirent *buf, size_t bufsize); + +typedef int op_open(void *ns, void *node, int omode, void **cookie); +typedef int op_close(void *ns, void *node, void *cookie); +typedef int op_free_cookie(void *ns, void *node, void *cookie); +typedef int op_read(void *ns, void *node, void *cookie, off_t pos, void *buf, + size_t *len); +typedef int op_write(void *ns, void *node, void *cookie, off_t pos, + const void *buf, size_t *len); +typedef int op_readv(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, + size_t count, size_t *len); +typedef int op_writev(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, + size_t count, size_t *len); +typedef int op_ioctl(void *ns, void *node, void *cookie, int cmd, void *buf, + size_t len); +typedef int op_setflags(void *ns, void *node, void *cookie, int flags); + +typedef int op_rstat(void *ns, void *node, struct stat *); +typedef int op_wstat(void *ns, void *node, struct stat *, long mask); +typedef int op_fsync(void *ns, void *node); + +typedef int op_select(void *ns, void *node, void *cookie, uint8 event, + uint32 ref, selectsync *sync); +typedef int op_deselect(void *ns, void *node, void *cookie, uint8 event, + selectsync *sync); + +typedef int op_initialize(const char *devname, void *parms, size_t len); +typedef int op_mount(nspace_id nsid, const char *devname, ulong flags, + void *parms, size_t len, void **data, vnode_id *vnid); +typedef int op_unmount(void *ns); +typedef int op_sync(void *ns); +typedef int op_rfsstat(void *ns, struct fs_info *); +typedef int op_wfsstat(void *ns, struct fs_info *, long mask); + + +typedef int op_open_attrdir(void *ns, void *node, void **cookie); +typedef int op_close_attrdir(void *ns, void *node, void *cookie); +typedef int op_rewind_attrdir(void *ns, void *node, void *cookie); +typedef int op_read_attrdir(void *ns, void *node, void *cookie, long *num, + struct dirent *buf, size_t bufsize); +typedef int op_remove_attr(void *ns, void *node, const char *name); +typedef int op_rename_attr(void *ns, void *node, const char *oldname, + const char *newname); +typedef int op_stat_attr(void *ns, void *node, const char *name, + struct attr_info *buf); + +typedef int op_write_attr(void *ns, void *node, const char *name, int type, + const void *buf, size_t *len, off_t pos); +typedef int op_read_attr(void *ns, void *node, const char *name, int type, + void *buf, size_t *len, off_t pos); + +typedef int op_open_indexdir(void *ns, void **cookie); +typedef int op_close_indexdir(void *ns, void *cookie); +typedef int op_rewind_indexdir(void *ns, void *cookie); +typedef int op_read_indexdir(void *ns, void *cookie, long *num, + struct dirent *buf, size_t bufsize); +typedef int op_create_index(void *ns, const char *name, int type, int flags); +typedef int op_remove_index(void *ns, const char *name); +typedef int op_rename_index(void *ns, const char *oldname, + const char *newname); +typedef int op_stat_index(void *ns, const char *name, struct index_info *buf); + +typedef int op_open_query(void *ns, const char *query, ulong flags, + port_id port, long token, void **cookie); +typedef int op_close_query(void *ns, void *cookie); +typedef int op_read_query(void *ns, void *cookie, long *num, + struct dirent *buf, size_t bufsize); + +typedef struct vnode_ops { + op_read_vnode (*read_vnode); + op_write_vnode (*write_vnode); + op_remove_vnode (*remove_vnode); + op_secure_vnode (*secure_vnode); + op_walk (*walk); + op_access (*access); + op_create (*create); + op_mkdir (*mkdir); + op_symlink (*symlink); + op_link (*link); + op_rename (*rename); + op_unlink (*unlink); + op_rmdir (*rmdir); + op_readlink (*readlink); + op_opendir (*opendir); + op_closedir (*closedir); + op_free_cookie (*free_dircookie); + op_rewinddir (*rewinddir); + op_readdir (*readdir); + op_open (*open); + op_close (*close); + op_free_cookie (*free_cookie); + op_read (*read); + op_write (*write); + op_readv (*readv); + op_writev (*writev); + op_ioctl (*ioctl); + op_setflags (*setflags); + op_rstat (*rstat); + op_wstat (*wstat); + op_fsync (*fsync); + op_initialize (*initialize); + op_mount (*mount); + op_unmount (*unmount); + op_sync (*sync); + op_rfsstat (*rfsstat); + op_wfsstat (*wfsstat); + op_select (*select); + op_deselect (*deselect); + op_open_indexdir (*open_indexdir); + op_close_indexdir (*close_indexdir); + op_free_cookie (*free_indexdircookie); + op_rewind_indexdir (*rewind_indexdir); + op_read_indexdir (*read_indexdir); + op_create_index (*create_index); + op_remove_index (*remove_index); + op_rename_index (*rename_index); + op_stat_index (*stat_index); + op_open_attrdir (*open_attrdir); + op_close_attrdir (*close_attrdir); + op_free_cookie (*free_attrdircookie); + op_rewind_attrdir (*rewind_attrdir); + op_read_attrdir (*read_attrdir); + op_write_attr (*write_attr); + op_read_attr (*read_attr); + op_remove_attr (*remove_attr); + op_rename_attr (*rename_attr); + op_stat_attr (*stat_attr); + op_open_query (*open_query); + op_close_query (*close_query); + op_free_cookie (*free_querycookie); + op_read_query (*read_query); +} vnode_ops; + +extern _IMPEXP_KERNEL int new_path(const char *path, char **copy); +extern _IMPEXP_KERNEL void free_path(char *p); + +extern _IMPEXP_KERNEL int notify_listener(int op, nspace_id nsid, + vnode_id vnida, vnode_id vnidb, + vnode_id vnidc, const char *name); +extern _IMPEXP_KERNEL void notify_select_event(selectsync *sync, uint32 ref); +extern _IMPEXP_KERNEL int send_notification(port_id port, long token, + ulong what, long op, nspace_id nsida, + nspace_id nsidb, vnode_id vnida, + vnode_id vnidb, vnode_id vnidc, + const char *name); +extern _IMPEXP_KERNEL int get_vnode(nspace_id nsid, vnode_id vnid, void **data); +extern _IMPEXP_KERNEL int put_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int new_vnode(nspace_id nsid, vnode_id vnid, void *data); +extern _IMPEXP_KERNEL int remove_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int unremove_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int is_vnode_removed(nspace_id nsid, vnode_id vnid); + + +extern _EXPORT vnode_ops fs_entry; +extern _EXPORT int32 api_version; + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocket_internal.h b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocket_internal.h new file mode 100644 index 0000000000..e44e55c7b8 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocket_internal.h @@ -0,0 +1,166 @@ +#ifndef _KSOCKET_INTERNAL_H + +#define _KSOCKET_INTERNAL_H + +#include + +struct ks_param_header +{ + port_id port; +}; + +struct ks_reply_header +{ + int error; +}; + +struct ks_socket_param +{ + struct ks_param_header header; + int family,type,proto; +}; + +struct ks_socket_reply +{ + struct ks_reply_header header; + int result; +}; + +struct ks_bind_param +{ + struct ks_param_header header; + int fd; + int size; + char addr[1]; +}; + +struct ks_bind_reply +{ + struct ks_reply_header header; + int result; +}; + +struct ks_getsockname_param +{ + struct ks_param_header header; + int fd; + int size; +}; + +struct ks_getsockname_reply +{ + struct ks_reply_header header; + int result; + int size; + char addr[1]; +}; + +struct ks_recvfrom_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; + int fromlen; +}; + +struct ks_recvfrom_reply +{ + struct ks_reply_header header; + ssize_t result; + int fromlen; + char data[1]; +}; + +struct ks_sendto_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; + int tolen; + char data[1]; +}; + +struct ks_sendto_reply +{ + struct ks_reply_header header; + ssize_t result; +}; + +struct ks_recv_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; +}; + +struct ks_recv_reply +{ + struct ks_reply_header header; + ssize_t result; + char data[1]; +}; + +struct ks_send_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; + char data[1]; +}; + +struct ks_send_reply +{ + struct ks_reply_header header; + ssize_t result; +}; + +struct ks_listen_param +{ + struct ks_param_header header; + int fd,backlog; +}; + +struct ks_listen_reply +{ + struct ks_reply_header header; + int result; +}; + +struct ks_closesocket_param +{ + struct ks_param_header header; + int fd; +}; + +struct ks_closesocket_reply +{ + struct ks_reply_header header; + int result; +}; + +enum +{ + KS_SOCKET, + KS_BIND, + KS_GETSOCKNAME, + KS_GETPEERNAME, + KS_CONNECT, + KS_ACCEPT, + KS_RECVFROM, + KS_SENDTO, + KS_RECV, + KS_SEND, + KS_LISTEN, + KS_CLOSESOCKET, + KS_MESSAGE, + KS_QUIT +}; + +#define KSOCKET_DAEMON_NAME "ksocket_daemon" +#define KSOCKETD_SIGNATURE "application/x-vnd.BareCode-ksocketd" + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocketd/ksocketd.cpp b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocketd/ksocketd.cpp new file mode 100644 index 0000000000..532db3d0d3 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocketd/ksocketd.cpp @@ -0,0 +1,387 @@ +#define DEBUG 1 +#include +#include +#include +#include +#include +#include +#include "ksocket_internal.h" + +sem_id printf_sem; + +static void send_reply (port_id port, const void *reply, size_t size) +{ + status_t result; + + do + { + result=write_port (port,0,reply,size); + } + while (result==B_INTERRUPTED); + + ASSERT (result>=B_OK); +} + +static void ks_socket (const struct ks_socket_param *param) +{ + struct ks_socket_reply reply; + + reply.result=socket (param->family,param->type,param->proto); + reply.header.error=errno; + + send_reply (param->header.port,&reply,sizeof(reply)); +} + +static void ks_multi1 (int32 code, const struct ks_bind_param *param) +{ + struct ks_bind_reply reply; + + if (code==KS_BIND) + reply.result=bind (param->fd,(const struct sockaddr *)param->addr,param->size); + else + reply.result=connect (param->fd,(const struct sockaddr *)param->addr,param->size); + + reply.header.error=errno; + + send_reply (param->header.port,&reply,sizeof(reply)); +} + +static void ks_multi2 (int32 code, const struct ks_getsockname_param *param) +{ + struct sockaddr *addr=(struct sockaddr *)malloc(param->size); + int size=param->size; + int result; + size_t replySize; + struct ks_getsockname_reply *reply; + + switch (code) + { + case KS_GETSOCKNAME: + result=getsockname(param->fd,addr,&size); + break; + case KS_GETPEERNAME: + result=getpeername(param->fd,addr,&size); + break; + case KS_ACCEPT: + result=accept(param->fd,addr,&size); + break; + } + + if (result<0) + size=0; + + replySize=sizeof(struct ks_getsockname_reply)+size; + reply=(struct ks_getsockname_reply *)malloc(replySize); + reply->result=result; + reply->header.error=errno; + + if (result>=0) + { + reply->size=size; + memcpy (reply->addr,addr,size); + } + + send_reply (param->header.port,reply,replySize); + + free (reply); + free (addr); +} + +static void ks_recvfrom (const struct ks_recvfrom_param *param) +{ + char *buffer=(char *)malloc(param->size); + struct sockaddr *addr=(struct sockaddr *)malloc(param->fromlen); + int fromlen=param->fromlen; + ssize_t result; + size_t replySize; + struct ks_recvfrom_reply *reply; + + result=recvfrom(param->fd,buffer,param->size,param->flags,addr,&fromlen); + + if (result<0) + replySize=sizeof(struct ks_recvfrom_reply); + else + replySize=sizeof(struct ks_recvfrom_reply)+fromlen+result; + + reply=(struct ks_recvfrom_reply *)malloc(replySize); + reply->result=result; + reply->header.error=errno; + + if (result>=0) + { + reply->fromlen=fromlen; + memcpy (reply->data,buffer,result); + memcpy (reply->data+result,addr,fromlen); + } + + send_reply (param->header.port,reply,replySize); + + free (reply); + free (addr); + free (buffer); +} + +static void ks_sendto (const struct ks_sendto_param *param) +{ + struct ks_sendto_reply reply; + + reply.result=sendto (param->fd,param->data,param->size,param->flags, + (const struct sockaddr *)(param->data+param->size), + param->tolen); + + reply.header.error=errno; + + send_reply (param->header.port,&reply,sizeof(reply)); +} + +static void ks_recv (const struct ks_recv_param *param) +{ + char *buffer=(char *)malloc(param->size); + ssize_t result; + size_t replySize; + struct ks_recv_reply *reply; + + result=recv(param->fd,buffer,param->size,param->flags); + + if (result<0) + replySize=sizeof(struct ks_recvfrom_reply); + else + replySize=sizeof(struct ks_recvfrom_reply)+result; + + reply=(struct ks_recv_reply *)malloc(replySize); + reply->result=result; + reply->header.error=errno; + + if (result>=0) + memcpy (reply->data,buffer,result); + + send_reply (param->header.port,reply,replySize); + + free (reply); + free (buffer); +} + +static void ks_send (const struct ks_send_param *param) +{ + struct ks_send_reply reply; + + reply.result=send (param->fd,param->data,param->size,param->flags); + + reply.header.error=errno; + + send_reply (param->header.port,&reply,sizeof(reply)); +} + +static void ks_listen (const struct ks_listen_param *param) +{ + struct ks_listen_reply reply; + + reply.result=listen (param->fd,param->backlog); + reply.header.error=errno; + + send_reply (param->header.port,&reply,sizeof(reply)); +} + +static void ks_closesocket (const struct ks_closesocket_param *param) +{ + struct ks_closesocket_reply reply; + + reply.result=closesocket (param->fd); + reply.header.error=errno; + + send_reply (param->header.port,&reply,sizeof(reply)); +} + +static status_t client_func (void *buffer) +{ + thread_id from; + int32 code=receive_data (&from,NULL,0); + + ASSERT (code>=B_OK); + + switch (code) + { + case KS_SOCKET: + ks_socket ((const struct ks_socket_param *)buffer); + break; + + case KS_BIND: + case KS_CONNECT: + ks_multi1 (code,(const struct ks_bind_param *)buffer); + break; + + case KS_GETSOCKNAME: + case KS_GETPEERNAME: + case KS_ACCEPT: + ks_multi2 (code,(const struct ks_getsockname_param *)buffer); + break; + + case KS_RECVFROM: + ks_recvfrom ((const struct ks_recvfrom_param *)buffer); + break; + + case KS_SENDTO: + ks_sendto ((const struct ks_sendto_param *)buffer); + break; + + case KS_RECV: + ks_recv ((const struct ks_recv_param *)buffer); + break; + + case KS_SEND: + ks_send ((const struct ks_send_param *)buffer); + break; + + case KS_LISTEN: + ks_listen ((const struct ks_listen_param *)buffer); + break; + + case KS_CLOSESOCKET: + ks_closesocket ((const struct ks_closesocket_param *)buffer); + break; + + case KS_MESSAGE: + { + while (acquire_sem (printf_sem)==B_INTERRUPTED) ; + + printf ("%s\n",buffer); + + while (release_sem (printf_sem)==B_INTERRUPTED) ; + break; + } + } + + free (buffer); + + return B_OK; +} + +class CApplication : public BApplication +{ + port_id port; + thread_id fTID; + + static status_t WorkhorseWrapper (CApplication *me); + status_t Workhorse (); + + public: + CApplication (const char *signature); + + virtual void ReadyToRun(); + virtual bool QuitRequested(); +}; + +CApplication::CApplication(const char *signature) + : BApplication (signature) +{ +} + +void +CApplication::ReadyToRun() +{ + resume_thread (fTID=spawn_thread((thread_func)WorkhorseWrapper,"Workhorse",B_NORMAL_PRIORITY,this)); +} + +bool +CApplication::QuitRequested() +{ + if (!BApplication::QuitRequested()) + return false; + + while (write_port(port,KS_QUIT,NULL,0)==B_INTERRUPTED) + ; + + status_t result; + wait_for_thread (fTID,&result); + + return true; +} + +status_t +CApplication::WorkhorseWrapper(CApplication *me) +{ + return me->Workhorse(); +} + +status_t +CApplication::Workhorse() +{ + char *buffer; + ssize_t bufferSize; + int32 code; + thread_id tid; + status_t result; + BList clientList; + + printf_sem=create_sem (1,"printf_sem"); + + if (printf_sem=B_OK); + + buffer=(char *)malloc(bufferSize); + + do + { + result=read_port (port,&code,buffer,bufferSize); + } + while (result==B_INTERRUPTED); + + ASSERT (result>=B_OK); + + if (code==KS_QUIT) + break; + + tid=spawn_thread (client_func,"ksocketd_client",B_NORMAL_PRIORITY,buffer); + + ASSERT (tid>=B_OK); + + clientList.AddItem((void *)tid); + + result=resume_thread (tid); + + ASSERT (result>=B_OK); + + result=send_data (tid,code,NULL,0); + + ASSERT (result>=B_OK); + } + + for (int32 i=clientList.CountItems()-1;i>=0;i--) + { + thread_id tid=(thread_id)clientList.RemoveItem(i); + status_t result; + wait_for_thread (tid,&result); + } + + delete_sem (printf_sem); + delete_port (port); + + return B_OK; +} + +int main () +{ + CApplication app(KSOCKETD_SIGNATURE); + + app.Run(); + + return 0; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocketd/ksocketd.rsrc b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocketd/ksocketd.rsrc new file mode 100644 index 0000000000..48ebf1ff4e Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocketd/ksocketd.rsrc differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocketd/makefile b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocketd/makefile new file mode 100644 index 0000000000..5b31e2ce07 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/ksocketd/makefile @@ -0,0 +1,318 @@ +## BeOS Generic Makefile ## + +## Fill in the top section of this makefile to define exactly what sort of +## binary you are creating, and what sources, resources and libraries are +## needed to create it. The makefile will then determine the proper +## platform specific options. + +## Fill in the top section to define the binary being created and the makefile +## will make sure that all of the hard work is taken care of for you, for both +## PowerPC and Intel versions of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= ksocketd + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= APP + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= ksocketd.cpp + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= ksocketd.rsrc + +#specify additional libraries to link against +# if libName.so or libName.a is the name of the library to link against +# then simply specify Name in the LIBS list +# if there is another naming scheme use the full binary +# name: my_library.so or my_lib.a +# libroot.so never needs to be specified here, although libbe.so does +LIBS= be net + + +# specify the paths to directories where additional +# libraries are to be found. /boot/develop/lib/PLATFORM/ is +# already set. The paths can be full or relative to this +# makefile. The paths included may not be recursive, so +# specify all of the needed paths explicitly +# Directories containing source-files are automatically added. +LIBPATHS= + +# specify additional directories where header files can be found +# directories where sources are found are included automatically +# included. +INCPATHS= .. + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= + +# specify any symbols to be defined. The symbols will be +# set to a value of 1. For example specify DEBUG if you want +# DEBUG=1 to be set when compiling. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = + +# specify symbols +# if TRUE debug symbols will be created +SYMBOLS = + + +## Generic Makefile Rules --------------------------- +## DO NOT MODIFY BENEATH THIS LINE ----------------- + +# determine wheather running on x86 or ppc +MACHINE=$(shell uname -m) +ifeq ($(MACHINE), BePC) + CPU = x86 +else + CPU = ppc +endif + +# set the directory where object files and binaries will be created + OBJ_DIR := obj.$(CPU) + +# specify that the binary should be created in the object directory + TARGET := $(OBJ_DIR)/$(NAME) + +# specify the mimeset tool + MIMESET := mimeset + +# specify the tools for adding and removing resources + XRES = xres + +# SETTING: define debug symbols if desired +ifeq ($(SYMBOLS), TRUE) + CFLAGS += -g +endif + + +# platform specific settings + +# x86 Settings +ifeq ($(CPU), x86) +# set the compiler and compiler flags + CC = gcc + ##!! change next time : drivers get -no-fpic and -fpic goes away !! + CFLAGS += -fpic + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O1 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy + else + ifeq ($(WARNINGS), NONE) + + endif + endif + +# set the linker and linker flags + LD = gcc + LDFLAGS = + +# SETTING: set linker flags for each binary type + ifeq ($(TYPE), APP) + LDFLAGS += -Xlinker -soname=_APP_ + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -addon -Xlinker -soname=$(NAME) + else + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_ + endif + endif + endif + +else + +# ppc Settings +ifeq ($(CPU), ppc) +# set the compiler and compiler flags + CC = mwcc + CFLAGS += + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O7 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -w all + else + ifeq ($(WARNINGS), NONE) + CFLAGS += -w 0 + endif + endif + + # clear the standard environment variable + # now there are no standard libraries to link against + BELIBFILES= + +# set the linker and linker flags + LD = mwldppc + + ifeq ($(TYPE), APP) + LDFLAGS += + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -xms + endif + endif + + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nodefaults \ + -export all \ + -G \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/_KERNEL_ + else + # override the standard environment variable + LDFLAGS += -export pragma \ + -init _init_routine_ \ + -term _term_routine_ \ + -lroot \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/init_term_dyn.o \ + /boot/develop/lib/ppc/start_dyn.o + + endif + + +endif +endif + + +# psuedo-function for converting a list of source files in SRCS variable +# to a corresponding list of object files in $(OBJ_DIR)/xxx.o +# The "function" strips off the src file suffix (.ccp or .c or whatever) +# and then strips of the directory name, leaving just the root file name. +# It then appends the .o suffix and prepends the $(OBJ_DIR)/ path +define SRCS_LIST_TO_OBJS + $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ + $(basename $(notdir $(file)))))) +endef + +OBJS = $(SRCS_LIST_TO_OBJS) + +# create a unique list of paths to our sourcefiles +SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) + +# add source paths to VPATH if not already present +VPATH := +VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) + +# add source paths and include paths to INLCUDES if not already present +INCLUDES = $(foreach path, $(INCPATHS) $(SRC_PATHS), $(addprefix -I, $(path))) + + +# SETTING: add the -L prefix to all library paths to search +LINK_PATHS = $(foreach path, $(LIBPATHS) $(SRC_PATHS) , \ + $(addprefix -L, $(path))) + +# SETTING: add the -l prefix to all libs to be linked against +LINK_LIBS = $(foreach lib, $(LIBS), $(addprefix -l, $(lib))) + +# add to the linker flags +LDFLAGS += $(LINK_PATHS) $(LINK_LIBS) + +# SETTING: add the defines to the compiler flags +CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define))) + +# SETTING: use the archive tools if building a static library +# otherwise use the linker +ifeq ($(TYPE), STATIC) + BUILD_LINE = ar -cru $(NAME) $(OBJS) +else + BUILD_LINE = $(LD) -o $@ $(OBJS) $(LDFLAGS) +endif + +# create the resource instruction + ifeq ($(RSRCS), ) + DO_RSRCS := + else + DO_RSRCS := $(XRES) -o $(TARGET) $(RSRCS) + endif + + +# define the actual work to be done +default: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) $(RSRCS) + $(BUILD_LINE) + $(DO_RSRCS) + $(MIMESET) -f $@ + + +# rule to create the object file directory if needed +$(OBJ_DIR):: + @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 + +$(OBJ_DIR)/%.o : %.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cpp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.C + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CC + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CPP + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ + +$(OBJ_DIR)/ksocketd.o: ksocketd.cpp ../ksocket_internal.h + +# empty rule. Things that depend on this rule will always get triggered +FORCE: + +# The generic clean command. Delete everything in the object folder. +clean :: FORCE + -rm -rf $(OBJ_DIR) + +# remove just the application from the object folder +rmapp :: + -rm -f $(TARGET) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/libksocket/ksocket.c b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/libksocket/ksocket.c new file mode 100644 index 0000000000..ac8a037eb7 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/libksocket/ksocket.c @@ -0,0 +1,519 @@ +#include "ksocket_internal.h" +#include "ksocket.h" + +#include +#include +#include +#include +#include +#include +#include + +struct ks_globals +{ + port_id daemon; + + sem_id port_pool_sem; + port_id *port_pool; + int32 port_pool_count; + int32 port_pool_size; + int32 refcount; +}; + +struct ks_globals *ksocket_globals=NULL; + +static port_id acquire_port (); +static void release_port (port_id port); +static status_t send_call (int32 code, struct ks_param_header *param, size_t size, struct ks_reply_header **reply); +static int kmulti1 (int32 code, int fd, const struct sockaddr *addr, int size); +static int kmulti2 (int32 code, int fd, struct sockaddr *addr, int *size); + +port_id +acquire_port() +{ + port_id port; + + while (acquire_sem (ksocket_globals->port_pool_sem)==B_INTERRUPTED) + { + } + + if (ksocket_globals->port_pool_count==0) + { + port=create_port (1,"ksocket_port"); + set_port_owner (port,B_SYSTEM_TEAM); + + while (release_sem (ksocket_globals->port_pool_sem)==B_INTERRUPTED) + { + } + + return port; + } + + port=ksocket_globals->port_pool[ksocket_globals->port_pool_count-1]; + ksocket_globals->port_pool_count--; + + while (release_sem (ksocket_globals->port_pool_sem)==B_INTERRUPTED) + { + } + + return port; +} + +void +release_port(port_id port) +{ + while (acquire_sem (ksocket_globals->port_pool_sem)==B_INTERRUPTED) + { + } + + if (ksocket_globals->port_pool_count+1>ksocket_globals->port_pool_size) + { + ksocket_globals->port_pool_size+=8; + ksocket_globals->port_pool=(port_id *)realloc(ksocket_globals->port_pool,ksocket_globals->port_pool_size*sizeof(port_id)); + } + + ksocket_globals->port_pool[ksocket_globals->port_pool_count]=port; + ksocket_globals->port_pool_count++; + + while (release_sem (ksocket_globals->port_pool_sem)==B_INTERRUPTED) + { + } +} + +status_t +send_call(int32 code, struct ks_param_header *param, size_t size, struct ks_reply_header **reply) +{ + status_t result; + ssize_t bytes; + + param->port=acquire_port(); + + do + { + result=write_port (ksocket_globals->daemon,code,param,size); + } + while (result==B_INTERRUPTED); + + if (resultport); + return result; + } + + do + { + bytes=port_buffer_size (param->port); + } + while (bytes==B_INTERRUPTED); + + if (bytesport); + return bytes; + } + + *reply=(struct ks_reply_header *)malloc(bytes); + + do + { + int32 dummy; + result=read_port (param->port,&dummy,*reply,bytes); + } + while (result==B_INTERRUPTED); + + if (resultport); + return result; + } + + release_port (param->port); + return B_OK; +} + + +extern int ksocket (int family, int type, int proto) +{ + struct ks_socket_param param; + struct ks_socket_reply *reply; + status_t result; + + param.family=family; + param.type=type; + param.proto=proto; + + result=send_call(KS_SOCKET,¶m.header,sizeof(param),(struct ks_reply_header **)&reply); + + if (resultresult; + + if (result<0) + errno=reply->header.error; + + free (reply); + + return result; +} + +int kmulti1 (int32 code, int fd, const struct sockaddr *addr, int size) +{ + size_t paramSize=sizeof(struct ks_bind_param)+size; + struct ks_bind_param *param=(struct ks_bind_param *)malloc(paramSize); + struct ks_bind_reply *reply; + status_t result; + + param->fd=fd; + param->size=size; + memcpy (param->addr,addr,size); + + result=send_call(code,¶m->header,paramSize,(struct ks_reply_header **)&reply); + + if (resultresult; + + if (result<0) + errno=reply->header.error; + + free (reply); + free (param); + + return result; +} + +int kmulti2 (int32 code, int fd, struct sockaddr *addr, int *size) +{ + struct ks_getsockname_param param; + struct ks_getsockname_reply *reply; + status_t result; + + param.fd=fd; + param.size=*size; + + result=send_call (code,¶m.header,sizeof(param),(struct ks_reply_header **)&reply); + + if (resultresult; + + if (result<0) + errno=reply->header.error; + else + { + *size=reply->size; + memcpy (addr,reply->addr,reply->size); + } + + free (reply); + + return result; +} + +extern int kbind (int fd, const struct sockaddr *addr, int size) +{ + return kmulti1 (KS_BIND,fd,addr,size); +} + +extern int kconnect (int fd, const struct sockaddr *addr, int size) +{ + return kmulti1 (KS_CONNECT,fd,addr,size); +} + +extern int kgetsockname (int fd, struct sockaddr *addr, int *size) +{ + return kmulti2 (KS_GETSOCKNAME,fd,addr,size); +} + +extern int kgetpeername (int fd, struct sockaddr *addr, int *size) +{ + return kmulti2 (KS_GETPEERNAME,fd,addr,size); +} + +extern int kaccept (int fd, struct sockaddr *addr, int *size) +{ + return kmulti2 (KS_ACCEPT,fd,addr,size); +} + +extern ssize_t krecvfrom (int fd, void *buf, size_t size, int flags, + struct sockaddr *from, int *fromlen) +{ + struct ks_recvfrom_param param; + struct ks_recvfrom_reply *reply; + status_t result; + + param.fd=fd; + param.size=size; + param.flags=flags; + param.fromlen=*fromlen; + + result=send_call (KS_RECVFROM,¶m.header,sizeof(param),(struct ks_reply_header **)&reply); + + if (resultresult; + + if (result<0) + errno=reply->header.error; + else + { + memcpy (buf,reply->data,result); + *fromlen=reply->fromlen; + memcpy (from,reply->data+result,reply->fromlen); + } + + free (reply); + + return result; +} + +extern ssize_t ksendto (int fd, const void *buf, size_t size, int flags, + const struct sockaddr *to, int tolen) +{ + size_t paramSize=sizeof(struct ks_sendto_param)+size+tolen; + struct ks_sendto_param *param=(struct ks_sendto_param *)malloc(paramSize); + struct ks_sendto_reply *reply; + status_t result; + + param->fd=fd; + param->size=size; + param->flags=flags; + param->tolen=tolen; + memcpy (param->data,buf,size); + memcpy (param->data+size,to,tolen); + + result=send_call(KS_SENDTO,¶m->header,paramSize,(struct ks_reply_header **)&reply); + + if (resultresult; + + if (result<0) + errno=reply->header.error; + + free (reply); + free (param); + + return result; +} + +extern ssize_t ksend (int fd, const void *buf, size_t size, int flags) +{ + size_t paramSize=sizeof(struct ks_send_param)+size; + struct ks_send_param *param=(struct ks_send_param *)malloc(paramSize); + struct ks_send_reply *reply; + status_t result; + + param->fd=fd; + param->size=size; + param->flags=flags; + memcpy (param->data,buf,size); + + result=send_call(KS_SEND,¶m->header,paramSize,(struct ks_reply_header **)&reply); + + if (resultresult; + + if (result<0) + errno=reply->header.error; + + free (reply); + free (param); + + return result; +} + +extern ssize_t krecv (int fd, void *buf, size_t size, int flags) +{ + struct ks_recv_param param; + struct ks_recv_reply *reply; + status_t result; + + param.fd=fd; + param.size=size; + param.flags=flags; + + result=send_call (KS_RECV,¶m.header,sizeof(param),(struct ks_reply_header **)&reply); + + if (resultresult; + + if (result<0) + errno=reply->header.error; + else + memcpy (buf,reply->data,result); + + free (reply); + + return result; +} + +extern int klisten (int fd, int backlog) +{ + struct ks_listen_param param; + struct ks_listen_reply *reply; + status_t result; + + param.fd=fd; + param.backlog=backlog; + + result=send_call(KS_LISTEN,¶m.header,sizeof(param),(struct ks_reply_header **)&reply); + + if (resultresult; + + if (result<0) + errno=reply->header.error; + + free (reply); + + return result; +} + +extern int kclosesocket (int fd) +{ + struct ks_closesocket_param param; + struct ks_closesocket_reply *reply; + status_t result; + + param.fd=fd; + + result=send_call(KS_CLOSESOCKET,¶m.header,sizeof(param),(struct ks_reply_header **)&reply); + + if (resultresult; + + if (result<0) + errno=reply->header.error; + + free (reply); + + return result; +} + +extern status_t +ksocket_init() +{ + if (ksocket_globals) + { + ksocket_globals->refcount++; + + return B_OK; + } + + ksocket_globals=(struct ks_globals *)malloc(sizeof(struct ks_globals)); + + ksocket_globals->refcount=1; + ksocket_globals->daemon=find_port (KSOCKET_DAEMON_NAME); + + if (ksocket_globals->daemonport_pool_sem=create_sem(1,"port_pool_sem"); + + if (ksocket_globals->port_pool_semdaemon); + + free (ksocket_globals); + ksocket_globals=NULL; + + return B_ERROR; + } + + set_sem_owner (ksocket_globals->port_pool_sem,B_SYSTEM_TEAM); + + ksocket_globals->port_pool=NULL; + ksocket_globals->port_pool_count=0; + ksocket_globals->port_pool_size=0; + + return B_OK; +} + +extern status_t +ksocket_cleanup() +{ + int32 i; + + ksocket_globals->refcount--; + if (ksocket_globals->refcount>0) + return B_OK; + + for (i=0;iport_pool_count;i++) + delete_port (ksocket_globals->port_pool[i]); + + free (ksocket_globals->port_pool); + + delete_sem (ksocket_globals->port_pool_sem); + + free (ksocket_globals); + ksocket_globals=NULL; + + return B_OK; +} + +extern void kmessage (const char *format, ...) +{ + status_t result; + char msg[256]; + + va_list l; + va_start (l,format); + vsprintf (msg,format,l); + va_end (l); + + do + { + result=write_port (ksocket_globals->daemon,KS_MESSAGE,msg,strlen(msg)+1); + } + while (result==B_INTERRUPTED); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/libksocket/ksocket.h b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/libksocket/ksocket.h new file mode 100644 index 0000000000..1b52c9c324 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/libksocket/ksocket.h @@ -0,0 +1,31 @@ +#ifndef _KSOCKET_H + +#define _KSOCKET_H + +#include + +int ksocket (int family, int type, int proto); +int kbind (int fd, const struct sockaddr *addr, int size); +int kconnect (int fd, const struct sockaddr *addr, int size); +int kgetsockname (int fd, struct sockaddr *addr, int *size); +int kgetpeername (int fd, struct sockaddr *addr, int *size); +int kaccept (int fd, struct sockaddr *addr, int *size); + +ssize_t krecvfrom (int fd, void *buf, size_t size, int flags, + struct sockaddr *from, int *fromlen); + +ssize_t ksendto (int fd, const void *buf, size_t size, int flags, + const struct sockaddr *to, int tolen); + +ssize_t krecv (int fd, void *buf, size_t size, int flags); +ssize_t ksend (int fd, const void *buf, size_t size, int flags); + +int klisten (int fd, int backlog); +int kclosesocket (int fd); + +status_t ksocket_init (); +status_t ksocket_cleanup (); + +void kmessage (const char *format, ...); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/libksocket/makefile b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/libksocket/makefile new file mode 100644 index 0000000000..3ad6c483ec --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/ksocket_v3/libksocket/makefile @@ -0,0 +1,318 @@ +## BeOS Generic Makefile ## + +## Fill in the top section of this makefile to define exactly what sort of +## binary you are creating, and what sources, resources and libraries are +## needed to create it. The makefile will then determine the proper +## platform specific options. + +## Fill in the top section to define the binary being created and the makefile +## will make sure that all of the hard work is taken care of for you, for both +## PowerPC and Intel versions of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= libksocket.a + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= STATIC + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= ksocket.c + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +#specify additional libraries to link against +# if libName.so or libName.a is the name of the library to link against +# then simply specify Name in the LIBS list +# if there is another naming scheme use the full binary +# name: my_library.so or my_lib.a +# libroot.so never needs to be specified here, although libbe.so does +LIBS= + + +# specify the paths to directories where additional +# libraries are to be found. /boot/develop/lib/PLATFORM/ is +# already set. The paths can be full or relative to this +# makefile. The paths included may not be recursive, so +# specify all of the needed paths explicitly +# Directories containing source-files are automatically added. +LIBPATHS= + +# specify additional directories where header files can be found +# directories where sources are found are included automatically +# included. +INCPATHS= .. + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= + +# specify any symbols to be defined. The symbols will be +# set to a value of 1. For example specify DEBUG if you want +# DEBUG=1 to be set when compiling. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = + +# specify symbols +# if TRUE debug symbols will be created +SYMBOLS = + + +## Generic Makefile Rules --------------------------- +## DO NOT MODIFY BENEATH THIS LINE ----------------- + +# determine wheather running on x86 or ppc +MACHINE=$(shell uname -m) +ifeq ($(MACHINE), BePC) + CPU = x86 +else + CPU = ppc +endif + +# set the directory where object files and binaries will be created + OBJ_DIR := obj.$(CPU) + +# specify that the binary should be created in the object directory + TARGET := $(OBJ_DIR)/$(NAME) + +# specify the mimeset tool + MIMESET := mimeset + +# specify the tools for adding and removing resources + XRES = xres + +# SETTING: define debug symbols if desired +ifeq ($(SYMBOLS), TRUE) + CFLAGS += -g +endif + + +# platform specific settings + +# x86 Settings +ifeq ($(CPU), x86) +# set the compiler and compiler flags + CC = gcc + ##!! change next time : drivers get -no-fpic and -fpic goes away !! + CFLAGS += -fpic + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O1 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy + else + ifeq ($(WARNINGS), NONE) + + endif + endif + +# set the linker and linker flags + LD = gcc + LDFLAGS = + +# SETTING: set linker flags for each binary type + ifeq ($(TYPE), APP) + LDFLAGS += -Xlinker -soname=_APP_ + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -addon -Xlinker -soname=$(NAME) + else + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_ + endif + endif + endif + +else + +# ppc Settings +ifeq ($(CPU), ppc) +# set the compiler and compiler flags + CC = mwcc + CFLAGS += + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O7 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -w all + else + ifeq ($(WARNINGS), NONE) + CFLAGS += -w 0 + endif + endif + + # clear the standard environment variable + # now there are no standard libraries to link against + BELIBFILES= + +# set the linker and linker flags + LD = mwldppc + + ifeq ($(TYPE), APP) + LDFLAGS += + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -xms + endif + endif + + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nodefaults \ + -export all \ + -G \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/_KERNEL_ + else + # override the standard environment variable + LDFLAGS += -export pragma \ + -init _init_routine_ \ + -term _term_routine_ \ + -lroot \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/init_term_dyn.o \ + /boot/develop/lib/ppc/start_dyn.o + + endif + + +endif +endif + + +# psuedo-function for converting a list of source files in SRCS variable +# to a corresponding list of object files in $(OBJ_DIR)/xxx.o +# The "function" strips off the src file suffix (.ccp or .c or whatever) +# and then strips of the directory name, leaving just the root file name. +# It then appends the .o suffix and prepends the $(OBJ_DIR)/ path +define SRCS_LIST_TO_OBJS + $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ + $(basename $(notdir $(file)))))) +endef + +OBJS = $(SRCS_LIST_TO_OBJS) + +# create a unique list of paths to our sourcefiles +SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) + +# add source paths to VPATH if not already present +VPATH := +VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) + +# add source paths and include paths to INLCUDES if not already present +INCLUDES = $(foreach path, $(INCPATHS) $(SRC_PATHS), $(addprefix -I, $(path))) + + +# SETTING: add the -L prefix to all library paths to search +LINK_PATHS = $(foreach path, $(LIBPATHS) $(SRC_PATHS) , \ + $(addprefix -L, $(path))) + +# SETTING: add the -l prefix to all libs to be linked against +LINK_LIBS = $(foreach lib, $(LIBS), $(addprefix -l, $(lib))) + +# add to the linker flags +LDFLAGS += $(LINK_PATHS) $(LINK_LIBS) + +# SETTING: add the defines to the compiler flags +CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define))) + +# SETTING: use the archive tools if building a static library +# otherwise use the linker +ifeq ($(TYPE), STATIC) + BUILD_LINE = ar -cru $(OBJ_DIR)/$(NAME) $(OBJS) +else + BUILD_LINE = $(LD) -o $@ $(OBJS) $(LDFLAGS) +endif + +# create the resource instruction + ifeq ($(RSRCS), ) + DO_RSRCS := + else + DO_RSRCS := $(XRES) -o $(TARGET) $(RSRCS) + endif + + +# define the actual work to be done +default: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) $(RSRCS) + $(BUILD_LINE) + $(DO_RSRCS) + $(MIMESET) -f $@ + + +# rule to create the object file directory if needed +$(OBJ_DIR):: + @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 + +$(OBJ_DIR)/%.o : %.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cpp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.C + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CC + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CPP + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ + +# empty rule. Things that depend on this rule will always get triggered +FORCE: + +# The generic clean command. Delete everything in the object folder. +clean :: FORCE + -rm -rf $(OBJ_DIR) + +# remove just the application from the object folder +rmapp :: + -rm -f $(TARGET) + +$(OBJ_DIR)/ksocket.o: ksocket.c ../ksocket_internal.h ksocket.h diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/makefile b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/makefile new file mode 100644 index 0000000000..f89113ddea --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/makefile @@ -0,0 +1,316 @@ +## BeOS Generic Makefile ## + +## Fill in the top section of this makefile to define exactly what sort of +## binary you are creating, and what sources, resources and libraries are +## needed to create it. The makefile will then determine the proper +## platform specific options. + +## Fill in the top section to define the binary being created and the makefile +## will make sure that all of the hard work is taken care of for you, for both +## PowerPC and Intel versions of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= beserved_client + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= DRIVER + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= nfs_add_on.c btClient.c readerWriter.c + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +#specify additional libraries to link against +# if libName.so or libName.a is the name of the library to link against +# then simply specify Name in the LIBS list +# if there is another naming scheme use the full binary +# name: my_library.so or my_lib.a +# libroot.so never needs to be specified here, although libbe.so does +LIBS= + +# specify the paths to directories where additional +# libraries are to be found. /boot/develop/lib/PLATFORM/ is +# already set. The paths can be full or relative to this +# makefile. The paths included may not be recursive, so +# specify all of the needed paths explicitly +# Directories containing source-files are automatically added. +LIBPATHS= + +# specify additional directories where header files can be found +# directories where sources are found are included automatically +# included. +INCPATHS= /boot/develop/headers/be/bone/sys + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= FULL + +# specify any symbols to be defined. The symbols will be +# set to a value of 1. For example specify DEBUG if you want +# DEBUG=1 to be set when compiling. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = + +# specify symbols +# if TRUE debug symbols will be created +SYMBOLS = + + +## Generic Makefile Rules --------------------------- +## DO NOT MODIFY BENEATH THIS LINE ----------------- + +# determine wheather running on x86 or ppc +MACHINE=$(shell uname -m) +ifeq ($(MACHINE), BePC) + CPU = x86 +else + CPU = ppc +endif + +# set the directory where object files and binaries will be created + OBJ_DIR := obj.$(CPU) + +# specify that the binary should be created in the object directory + TARGET := $(OBJ_DIR)/$(NAME) + +# specify the mimeset tool + MIMESET := mimeset + +# specify the tools for adding and removing resources + XRES = xres + +# SETTING: define debug symbols if desired +ifeq ($(SYMBOLS), TRUE) + CFLAGS += -g +endif + + +# platform specific settings + +# x86 Settings +ifeq ($(CPU), x86) +# set the compiler and compiler flags + CC = gcc + ##!! change next time : drivers get -no-fpic and -fpic goes away !! + CFLAGS += -fpic + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O1 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy + else + ifeq ($(WARNINGS), NONE) + + endif + endif + +# set the linker and linker flags + LD = gcc + LDFLAGS = + +# SETTING: set linker flags for each binary type + ifeq ($(TYPE), APP) + LDFLAGS += -Xlinker -soname=_APP_ + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -addon -Xlinker -soname=$(NAME) + else + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_ + endif + endif + endif + +else + +# ppc Settings +ifeq ($(CPU), ppc) +# set the compiler and compiler flags + CC = mwcc + CFLAGS += + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O7 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -w all + else + ifeq ($(WARNINGS), NONE) + CFLAGS += -w 0 + endif + endif + + # clear the standard environment variable + # now there are no standard libraries to link against + BELIBFILES= + +# set the linker and linker flags + LD = mwldppc + + ifeq ($(TYPE), APP) + LDFLAGS += + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -xms + endif + endif + + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nodefaults \ + -export all \ + -G \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/_KERNEL_ + else + # override the standard environment variable + LDFLAGS += -export pragma \ + -init _init_routine_ \ + -term _term_routine_ \ + -lroot \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/init_term_dyn.o \ + /boot/develop/lib/ppc/start_dyn.o + + endif + + +endif +endif + + +# psuedo-function for converting a list of source files in SRCS variable +# to a corresponding list of object files in $(OBJ_DIR)/xxx.o +# The "function" strips off the src file suffix (.ccp or .c or whatever) +# and then strips of the directory name, leaving just the root file name. +# It then appends the .o suffix and prepends the $(OBJ_DIR)/ path +define SRCS_LIST_TO_OBJS + $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ + $(basename $(notdir $(file)))))) +endef + +OBJS = $(SRCS_LIST_TO_OBJS) + +# create a unique list of paths to our sourcefiles +SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) + +# add source paths to VPATH if not already present +VPATH := +VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) + +# add source paths and include paths to INLCUDES if not already present +INCLUDES = $(foreach path, $(INCPATHS) $(SRC_PATHS), $(addprefix -I, $(path))) + + +# SETTING: add the -L prefix to all library paths to search +LINK_PATHS = $(foreach path, $(LIBPATHS) $(SRC_PATHS) , \ + $(addprefix -L, $(path))) + +# SETTING: add the -l prefix to all libs to be linked against +LINK_LIBS = $(foreach lib, $(LIBS), $(addprefix -l, $(lib))) + +# add to the linker flags +LDFLAGS += $(LINK_PATHS) $(LINK_LIBS) + +# SETTING: add the defines to the compiler flags +CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define))) + +# SETTING: use the archive tools if building a static library +# otherwise use the linker +ifeq ($(TYPE), STATIC) + BUILD_LINE = ar -cru $(NAME) $(OBJS) +else + BUILD_LINE = $(LD) -o $@ $(OBJS) $(LDFLAGS) +endif + +# create the resource instruction + ifeq ($(RSRCS), ) + DO_RSRCS := + else + DO_RSRCS := $(XRES) -o $(TARGET) $(RSRCS) + endif + + +# define the actual work to be done +default: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) $(RSRCS) + $(BUILD_LINE) + $(DO_RSRCS) + $(MIMESET) -f $@ + + +# rule to create the object file directory if needed +$(OBJ_DIR):: + @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 + +$(OBJ_DIR)/%.o : %.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cpp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.C + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CC + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CPP + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ + + +# empty rule. Things that depend on this rule will always get triggered +FORCE: + +# The generic clean command. Delete everything in the object folder. +clean :: FORCE + -rm -rf $(OBJ_DIR) + +# remove just the application from the object folder +rmapp :: + -rm -f $(TARGET) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/makefile.bone b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/makefile.bone new file mode 100644 index 0000000000..f89113ddea --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/makefile.bone @@ -0,0 +1,316 @@ +## BeOS Generic Makefile ## + +## Fill in the top section of this makefile to define exactly what sort of +## binary you are creating, and what sources, resources and libraries are +## needed to create it. The makefile will then determine the proper +## platform specific options. + +## Fill in the top section to define the binary being created and the makefile +## will make sure that all of the hard work is taken care of for you, for both +## PowerPC and Intel versions of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= beserved_client + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= DRIVER + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= nfs_add_on.c btClient.c readerWriter.c + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +#specify additional libraries to link against +# if libName.so or libName.a is the name of the library to link against +# then simply specify Name in the LIBS list +# if there is another naming scheme use the full binary +# name: my_library.so or my_lib.a +# libroot.so never needs to be specified here, although libbe.so does +LIBS= + +# specify the paths to directories where additional +# libraries are to be found. /boot/develop/lib/PLATFORM/ is +# already set. The paths can be full or relative to this +# makefile. The paths included may not be recursive, so +# specify all of the needed paths explicitly +# Directories containing source-files are automatically added. +LIBPATHS= + +# specify additional directories where header files can be found +# directories where sources are found are included automatically +# included. +INCPATHS= /boot/develop/headers/be/bone/sys + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= FULL + +# specify any symbols to be defined. The symbols will be +# set to a value of 1. For example specify DEBUG if you want +# DEBUG=1 to be set when compiling. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = + +# specify symbols +# if TRUE debug symbols will be created +SYMBOLS = + + +## Generic Makefile Rules --------------------------- +## DO NOT MODIFY BENEATH THIS LINE ----------------- + +# determine wheather running on x86 or ppc +MACHINE=$(shell uname -m) +ifeq ($(MACHINE), BePC) + CPU = x86 +else + CPU = ppc +endif + +# set the directory where object files and binaries will be created + OBJ_DIR := obj.$(CPU) + +# specify that the binary should be created in the object directory + TARGET := $(OBJ_DIR)/$(NAME) + +# specify the mimeset tool + MIMESET := mimeset + +# specify the tools for adding and removing resources + XRES = xres + +# SETTING: define debug symbols if desired +ifeq ($(SYMBOLS), TRUE) + CFLAGS += -g +endif + + +# platform specific settings + +# x86 Settings +ifeq ($(CPU), x86) +# set the compiler and compiler flags + CC = gcc + ##!! change next time : drivers get -no-fpic and -fpic goes away !! + CFLAGS += -fpic + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O1 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy + else + ifeq ($(WARNINGS), NONE) + + endif + endif + +# set the linker and linker flags + LD = gcc + LDFLAGS = + +# SETTING: set linker flags for each binary type + ifeq ($(TYPE), APP) + LDFLAGS += -Xlinker -soname=_APP_ + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -addon -Xlinker -soname=$(NAME) + else + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_ + endif + endif + endif + +else + +# ppc Settings +ifeq ($(CPU), ppc) +# set the compiler and compiler flags + CC = mwcc + CFLAGS += + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O7 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -w all + else + ifeq ($(WARNINGS), NONE) + CFLAGS += -w 0 + endif + endif + + # clear the standard environment variable + # now there are no standard libraries to link against + BELIBFILES= + +# set the linker and linker flags + LD = mwldppc + + ifeq ($(TYPE), APP) + LDFLAGS += + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -xms + endif + endif + + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nodefaults \ + -export all \ + -G \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/_KERNEL_ + else + # override the standard environment variable + LDFLAGS += -export pragma \ + -init _init_routine_ \ + -term _term_routine_ \ + -lroot \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/init_term_dyn.o \ + /boot/develop/lib/ppc/start_dyn.o + + endif + + +endif +endif + + +# psuedo-function for converting a list of source files in SRCS variable +# to a corresponding list of object files in $(OBJ_DIR)/xxx.o +# The "function" strips off the src file suffix (.ccp or .c or whatever) +# and then strips of the directory name, leaving just the root file name. +# It then appends the .o suffix and prepends the $(OBJ_DIR)/ path +define SRCS_LIST_TO_OBJS + $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ + $(basename $(notdir $(file)))))) +endef + +OBJS = $(SRCS_LIST_TO_OBJS) + +# create a unique list of paths to our sourcefiles +SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) + +# add source paths to VPATH if not already present +VPATH := +VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) + +# add source paths and include paths to INLCUDES if not already present +INCLUDES = $(foreach path, $(INCPATHS) $(SRC_PATHS), $(addprefix -I, $(path))) + + +# SETTING: add the -L prefix to all library paths to search +LINK_PATHS = $(foreach path, $(LIBPATHS) $(SRC_PATHS) , \ + $(addprefix -L, $(path))) + +# SETTING: add the -l prefix to all libs to be linked against +LINK_LIBS = $(foreach lib, $(LIBS), $(addprefix -l, $(lib))) + +# add to the linker flags +LDFLAGS += $(LINK_PATHS) $(LINK_LIBS) + +# SETTING: add the defines to the compiler flags +CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define))) + +# SETTING: use the archive tools if building a static library +# otherwise use the linker +ifeq ($(TYPE), STATIC) + BUILD_LINE = ar -cru $(NAME) $(OBJS) +else + BUILD_LINE = $(LD) -o $@ $(OBJS) $(LDFLAGS) +endif + +# create the resource instruction + ifeq ($(RSRCS), ) + DO_RSRCS := + else + DO_RSRCS := $(XRES) -o $(TARGET) $(RSRCS) + endif + + +# define the actual work to be done +default: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) $(RSRCS) + $(BUILD_LINE) + $(DO_RSRCS) + $(MIMESET) -f $@ + + +# rule to create the object file directory if needed +$(OBJ_DIR):: + @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 + +$(OBJ_DIR)/%.o : %.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cpp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.C + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CC + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CPP + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ + + +# empty rule. Things that depend on this rule will always get triggered +FORCE: + +# The generic clean command. Delete everything in the object folder. +clean :: FORCE + -rm -rf $(OBJ_DIR) + +# remove just the application from the object folder +rmapp :: + -rm -f $(TARGET) diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/makefile.net_server b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/makefile.net_server new file mode 100644 index 0000000000..abc4389160 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/makefile.net_server @@ -0,0 +1,319 @@ +## BeOS Generic Makefile ## + +## Fill in the top section of this makefile to define exactly what sort of +## binary you are creating, and what sources, resources and libraries are +## needed to create it. The makefile will then determine the proper +## platform specific options. + +## Fill in the top section to define the binary being created and the makefile +## will make sure that all of the hard work is taken care of for you, for both +## PowerPC and Intel versions of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= beserved_client + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= DRIVER + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= nfs_add_on.c btClient.c readerWriter.c + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +#specify additional libraries to link against +# if libName.so or libName.a is the name of the library to link against +# then simply specify Name in the LIBS list +# if there is another naming scheme use the full binary +# name: my_library.so or my_lib.a +# libroot.so never needs to be specified here, although libbe.so does +LIBS= ksocket + +# specify the paths to directories where additional +# libraries are to be found. /boot/develop/lib/PLATFORM/ is +# already set. The paths can be full or relative to this +# makefile. The paths included may not be recursive, so +# specify all of the needed paths explicitly +# Directories containing source-files are automatically added. +LIBPATHS=ksocket_v3/libksocket/$(OBJ_DIR) + +# specify additional directories where header files can be found +# directories where sources are found are included automatically +# included. +INCPATHS= ksocket_v3/libksocket + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= FULL + +# specify any symbols to be defined. The symbols will be +# set to a value of 1. For example specify DEBUG if you want +# DEBUG=1 to be set when compiling. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = + +# specify symbols +# if TRUE debug symbols will be created +SYMBOLS = + + +## Generic Makefile Rules --------------------------- +## DO NOT MODIFY BENEATH THIS LINE ----------------- + +# determine wheather running on x86 or ppc +MACHINE=$(shell uname -m) +ifeq ($(MACHINE), BePC) + CPU = x86 +else + CPU = ppc +endif + +# set the directory where object files and binaries will be created + OBJ_DIR := obj.$(CPU) + +# specify that the binary should be created in the object directory + TARGET := $(OBJ_DIR)/$(NAME) + +# specify the mimeset tool + MIMESET := mimeset + +# specify the tools for adding and removing resources + XRES = xres + +# SETTING: define debug symbols if desired +ifeq ($(SYMBOLS), TRUE) + CFLAGS += -g +endif + + +# platform specific settings + +# x86 Settings +ifeq ($(CPU), x86) +# set the compiler and compiler flags + CC = gcc + ##!! change next time : drivers get -no-fpic and -fpic goes away !! + CFLAGS += -fpic + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O1 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy + else + ifeq ($(WARNINGS), NONE) + + endif + endif + +# set the linker and linker flags + LD = gcc + LDFLAGS = + +# SETTING: set linker flags for each binary type + ifeq ($(TYPE), APP) + LDFLAGS += -Xlinker -soname=_APP_ + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -addon -Xlinker -soname=$(NAME) + else + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_ + endif + endif + endif + +else + +# ppc Settings +ifeq ($(CPU), ppc) +# set the compiler and compiler flags + CC = mwcc + CFLAGS += + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O7 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -w all + else + ifeq ($(WARNINGS), NONE) + CFLAGS += -w 0 + endif + endif + + # clear the standard environment variable + # now there are no standard libraries to link against + BELIBFILES= + +# set the linker and linker flags + LD = mwldppc + + ifeq ($(TYPE), APP) + LDFLAGS += + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -xms + endif + endif + + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nodefaults \ + -export all \ + -G \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/_KERNEL_ + else + # override the standard environment variable + LDFLAGS += -export pragma \ + -init _init_routine_ \ + -term _term_routine_ \ + -lroot \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/init_term_dyn.o \ + /boot/develop/lib/ppc/start_dyn.o + + endif + + +endif +endif + + +# psuedo-function for converting a list of source files in SRCS variable +# to a corresponding list of object files in $(OBJ_DIR)/xxx.o +# The "function" strips off the src file suffix (.ccp or .c or whatever) +# and then strips of the directory name, leaving just the root file name. +# It then appends the .o suffix and prepends the $(OBJ_DIR)/ path +define SRCS_LIST_TO_OBJS + $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ + $(basename $(notdir $(file)))))) +endef + +OBJS = $(SRCS_LIST_TO_OBJS) + +# create a unique list of paths to our sourcefiles +SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) + +# add source paths to VPATH if not already present +VPATH := +VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) + +# add source paths and include paths to INLCUDES if not already present +INCLUDES = $(foreach path, $(INCPATHS) $(SRC_PATHS), $(addprefix -I, $(path))) + + +# SETTING: add the -L prefix to all library paths to search +LINK_PATHS = $(foreach path, $(LIBPATHS) $(SRC_PATHS) , \ + $(addprefix -L, $(path))) + +# SETTING: add the -l prefix to all libs to be linked against +LINK_LIBS = $(foreach lib, $(LIBS), $(addprefix -l, $(lib))) + +# add to the linker flags +LDFLAGS += $(LINK_PATHS) $(LINK_LIBS) + +# SETTING: add the defines to the compiler flags +CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define))) + +# SETTING: use the archive tools if building a static library +# otherwise use the linker +ifeq ($(TYPE), STATIC) + BUILD_LINE = ar -cru $(NAME) $(OBJS) +else + BUILD_LINE = $(LD) -o $@ $(OBJS) $(LDFLAGS) +endif + +# create the resource instruction + ifeq ($(RSRCS), ) + DO_RSRCS := + else + DO_RSRCS := $(XRES) -o $(TARGET) $(RSRCS) + endif + + +# define the actual work to be done +default: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) $(RSRCS) ksocket_v3/libksocket/$(OBJ_DIR)/libksocket.a + $(BUILD_LINE) + $(DO_RSRCS) + $(MIMESET) -f $@ + + +# rule to create the object file directory if needed +$(OBJ_DIR):: + @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 + +$(OBJ_DIR)/%.o : %.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cpp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.C + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CC + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CPP + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ + + +# empty rule. Things that depend on this rule will always get triggered +FORCE: + +# The generic clean command. Delete everything in the object folder. +clean :: FORCE + -rm -rf $(OBJ_DIR) + +# remove just the application from the object folder +rmapp :: + -rm -f $(TARGET) + +ksocket_v3/libksocket/$(OBJ_DIR)/libksocket.a :: FORCE + cd ksocket_v3/libksocket; make diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/nfs_add_on.c b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/nfs_add_on.c new file mode 100644 index 0000000000..c4d48920e0 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/nfs_add_on.c @@ -0,0 +1,1478 @@ +#define _BUILDING_fs 1 + +#include "betalk.h" +#include "nfs_add_on.h" + +#ifndef BONE_VERSION +#include "ksocket.h" +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + + +_EXPORT vnode_ops fs_entry = +{ + (op_read_vnode *) &fs_read_vnode, + (op_write_vnode *) &fs_write_vnode, + (op_remove_vnode *) &fs_remove_vnode, + (op_secure_vnode *) &fs_secure_vnode, + (op_walk *) &fs_walk, + (op_access *) &fs_access, + (op_create *) &fs_create, + (op_mkdir *) &fs_mkdir, + (op_symlink *) &fs_symlink, + NULL, // &fs_link, + (op_rename *) &fs_rename, + (op_unlink *) &fs_unlink, + (op_rmdir *) &fs_rmdir, + (op_readlink *) &fs_readlink, + (op_opendir *) &fs_opendir, + (op_closedir *) &fs_closedir, + (op_free_cookie *) &fs_free_dircookie, + (op_rewinddir *) &fs_rewinddir, + (op_readdir *) &fs_readdir, + (op_open *) &fs_open, + (op_close *) &fs_close, + (op_free_cookie *) &fs_free_cookie, + (op_read *) &fs_read, + (op_write *) &fs_write, + NULL, // &fs_readv + NULL, // &fs_writev + NULL, // &fs_ioctl, + NULL, // &fs_setflags, + (op_rstat *) &fs_rstat, + (op_wstat *) &fs_wstat, + NULL, // &fs_fsync, + NULL, // &fs_initialize, + (op_mount *) &fs_mount, + (op_unmount *) &fs_unmount, + NULL, // &fs_sync, + (op_rfsstat *) &fs_rfsstat, + (op_wfsstat *) &fs_wfsstat, + NULL, // &fs_select + NULL, // &fs_deselect + (op_open_indexdir *) &fs_open_indexdir, + (op_close_indexdir *) &fs_close_indexdir, + (op_free_cookie *) &fs_free_indexdircookie, + (op_rewind_indexdir *) &fs_rewind_indexdir, + (op_read_indexdir *) &fs_read_indexdir, + (op_create_index *) &fsCreateIndex, + (op_remove_index *) &fsRemoveIndex, + NULL, // &fs_rename_index, + (op_stat_index *) &fsStatIndex, + (op_open_attrdir *) &fs_open_attribdir, + (op_close_attrdir *) &fs_close_attribdir, + (op_free_cookie *) &fs_free_attribdircookie, + (op_rewind_attrdir *) &fs_rewind_attribdir, + (op_read_attrdir *) &fs_read_attribdir, + (op_write_attr *) &fs_write_attrib, + (op_read_attr *) &fs_read_attrib, + (op_remove_attr *) &fs_remove_attrib, + NULL, // &fs_rename_attrib, + (op_stat_attr *) &fs_stat_attrib, + (op_open_query *) &fsOpenQuery, + (op_close_query *) &fsCloseQuery, + (op_free_cookie *) &fsFreeQueryCookie, + (op_read_query *) &fsReadQuery +}; + +_EXPORT int32 api_version = B_CUR_FS_API_VERSION; + +#ifdef BONE_VERSION + +struct bone_socket_info *bone_module = NULL; + +// bone_init() +// +bool bone_init() +{ + // Get a pointer to the BONE module. + get_module(BONE_SOCKET_MODULE, (module_info **) &bone_module); + return (bone_module != NULL); +} + +// bone_cleanup() +// +void bone_cleanup() +{ + put_module(BONE_SOCKET_MODULE); +} +#endif + +fs_node *create_node(fs_nspace *ns, vnode_id dir_vnid, const char *name, vnode_id file_vnid, bool newVnid) +{ + fs_node *newNode, *dupNode; + bool obsolete_nodes = false; + + while (acquire_sem(ns->sem) == B_INTERRUPTED); + + // Check to see if we find a node with this vnid. If we do, we need to know if it + // is the same file. This can be determined by examining the parent directory vnid + // and the filename. If everything matches, just return that node. + dupNode = getDuplicateVnid(ns, file_vnid); + if (dupNode) + { + // If it looks like this vnid, smells like this vnid, and tastes like this vnid, + // it must be this vnid. Alright, there's one exception -- symbolic links. These + // have the same vnid, but another name. + if (dupNode->parent == dir_vnid) + if (strcmp(dupNode->name, name) == 0) + { + release_sem(ns->sem); + return dupNode; + } + + // If we still found a vnid, but the parent directory vnid or filename don't + // match, then the original file is gone and another file has taken this vnid. + // Another user caused this change, which isn't registered with the local + // system's vnid table. In this case we adjust our internal node, and notify + // any listeners that the file has been renamed. Note that if this is the user + // that renamed the file, a duplicate notify_listener() call will be made by + // fs_rename(), but this seems to have no adverse effect. + dprintf("DUP VNID: %s, %s\n", name, dupNode->name); +// dprintf("notify_listener(B_ENTRY_MOVED, %s, %lu); -- duplicate vnid notice\n", name, file_vnid); +// notify_listener(B_ENTRY_MOVED, ns->nsid, dupNode->parent, dir_vnid, file_vnid, name); +// dupNode->parent = dir_vnid; +// strcpy(dupNode->name, name); +// release_sem(ns->sem); +// return dupNode; + } + + // Well, we now know we have a unique vnid. However, it is possible that the same + // file exists in our list under a different vnid. If a file is deleted, then re-created + // by another user and assigned a different vnid, then our existing vnid is obsolete + // and we must abandon it in favor of the replacement. Are we having fun yet? + dupNode = getDuplicateName(ns, dir_vnid, name); + if (dupNode) + if (dupNode->vnid != file_vnid) + { + dprintf("DUP NAME: %s (%lu)\n", dupNode->name, dupNode->vnid); + remove_obsolete_node(ns, dupNode); + obsolete_nodes = true; + } + + newNode = (fs_node *) malloc(sizeof(fs_node)); + if (newNode) + { + // Initialize the members of this new node. + newNode->parent = dir_vnid; + strcpy(newNode->name, name); + newNode->vnid = file_vnid; + + // Link the node in the list by making it the head. + newNode->next = ns->first; + ns->first = newNode; + + // If we're creating a new file, or we just had to delete our old vnid-cookie pair + // above, then we need to register this vnid with the newly created node. + if (newVnid || obsolete_nodes) + new_vnode(ns->nsid, file_vnid, newNode); + + dprintf("NEW NODE: %s (%lu)\n", name, file_vnid); +// print_vnode_list(ns); + } + + release_sem(ns->sem); + + if (obsolete_nodes) + notify_listener(B_ENTRY_CREATED, ns->nsid, dir_vnid, 0, file_vnid, name); + + return newNode; +} + +void print_vnode_list(fs_nspace *ns) +{ + fs_node *current; + + dprintf(" --- VNODE LIST --------------------------\n"); + current = ns->first; + while (current) + { + dprintf(" %-35s %lu\n", current->name, current->vnid); + current = current->next; + } + dprintf(" --- END OF LIST -------------------------\n"); +} + +void remove_obsolete_node(fs_nspace *ns, fs_node *node) +{ + release_sem(ns->sem); + + remove_node(ns, node->vnid); + + dprintf(" Notifying others that %s (%lu) was removed\n", node->name, node->vnid); + remove_vnode(ns->nsid, node->vnid); + put_vnode(ns->nsid, node->vnid); + notify_listener(B_ENTRY_REMOVED, ns->nsid, node->parent, 0, node->vnid, node->name); + + while (acquire_sem(ns->sem) == B_INTERRUPTED); +} + +void rename_node(fs_nspace *ns, vnode_id old_dir_vnid, const char *oldname, vnode_id new_dir_vnid, const char *newname, vnode_id file_vnid) +{ + fs_node *current; + + while (acquire_sem(ns->sem) == B_INTERRUPTED); + + // Check to see if we find a node with this vnid. If we do, we need to know if it + // is the same file. This can be determined by examining the parent directory vnid + // and the filename. If everything matches, rename the node to the new name. + current = ns->first; + while (current) + { + if (current->vnid == file_vnid) + if (current->parent == old_dir_vnid) + if (strcmp(current->name, oldname) == 0) + { + strcpy(current->name, newname); + current->parent = new_dir_vnid; + break; + } + + current = current->next; + } + + release_sem(ns->sem); +} + +fs_node *getDuplicateVnid(fs_nspace *ns, vnode_id vnid) +{ + fs_node *current; + + current = ns->first; + while (current && current->vnid != vnid) + current = current->next; + + return current; +} + +fs_node *getDuplicateName(fs_nspace *ns, vnode_id parent, const char *name) +{ + fs_node *current; + + current = ns->first; + while (current) + { + if (current->parent == parent) + if (strcmp(current->name, name) == 0) + break; + + current = current->next; + } + + return current; +} + +void remove_node(fs_nspace *ns, vnode_id vnid) +{ + fs_node *current; + fs_node *previous; + + while (acquire_sem(ns->sem) == B_INTERRUPTED); + + current = ns->first; + previous = NULL; + + while (current && current->vnid != vnid) + { + previous = current; + current = current->next; + } + + if (current) + { + if (previous) + previous->next = current->next; + else + ns->first = current->next; + + free(current); + } + + release_sem(ns->sem); +} + +// fs_read_vnode() +// +// Description: Allocate resources required to load the specified vnid. Also returns +// a reference to the vnode via the supplied pointer. +// +// Parameters: +// ns (in): Private file system structure +// vnid (in): vnid of the vnode to load +// r (in): ?? +// node (out): A reference to the vnode loaded +// +// Returns: +// B_OK if everything is successful, or +// EINVAL if the specified vnid is not found +// +extern int fs_read_vnode(fs_nspace *ns, vnode_id vnid, char r, fs_node **node) +{ + fs_node *current; + +//dprintf("fs_read_vnode()\n"); + *node = NULL; + + // If we need to acquire the semaphone to search the list, do so now. + if (!r) + while (acquire_sem(ns->sem) == B_INTERRUPTED); + + current = ns->first; + while (current && current->vnid != vnid) + current = current->next; + + // TODO: shouldn't we release the semaphore here? + // If the specified parameter is non-null, then return the node we found. + if (current && node) + *node = current; + + // Release the semaphore if necessary. + if (!r) + release_sem(ns->sem); + + return (current ? B_OK : EINVAL); +} + +// fs_write_vnode() +// +// Description: Free resources allocated with the sister function fs_read_vnode(). +// Parameters: +// ns (in): Private file system structure +// node (in): Node that can be freed +// r (in): ?? +// Returns: +// B_OK if everything is successful (always in our case) +// +extern int fs_write_vnode(fs_nspace *ns, fs_node *node, char r) +{ +//dprintf("fs_write_vnode()\n"); + // In our case, there aren't any resources to free, so there isn't anything + // for this function to do but return successfully. + return B_OK; +} + +// fs_walk() +// +// Description: This function is the single file system location where a path is +// traversed by name. Given a directory handle and a file name, this function returns +// the vnid of the file if it indeed exists. +// +// Parameters: +// ns (in): Private file system structure +// base (in): File handle of the directory to look in +// file (in): Name of the file to look for +// newpath (out): Name of the real file if the given file is a symbolic link +// vnid (out): Vnid of the file given by "file" +// +// Returns: +// B_OK if everything is successful, +// Otherwise an error code detailing the problem +// +extern int fs_walk(fs_nspace *ns, fs_node *base, const char *file, char **newpath, vnode_id *vnid) +{ + bool isLink; + void *dummy; + status_t result; + +//dprintf("fs_walk()\n"); + // If the file specified is the current directory, then that parameter provides + // the necessary vnid. Also note that the current directory entry cannot be a + // symbolic link. + if (!strcmp(".", file)) + { + *vnid = base->vnid; + isLink = false; + } + else + { + struct stat st; + status_t result; + + // Look up the requested entry, getting the stat structure and file handle + // filled in. + if ((result = btLookup(ns, base->vnid, file, vnid, &st)) != B_OK) + return result; + + // The vnid is the resulting file's inode. Once this is established, insert + // the new node in our list. + if (create_node(ns, base->vnid, file, *vnid, false) == NULL) + return ENOMEM; + + isLink = S_ISLNK(st.st_mode); + } + + if ((result = get_vnode(ns->nsid, *vnid, (void **) &dummy)) < B_OK) + return result; + + // If we've found a symbolic link, and the supplied character pointer is non-null, + // then the vnode layer is looking for the actual path. + if (isLink && newpath) + { + char path[B_PATH_NAME_LENGTH + 1]; + size_t pathLen = B_PATH_NAME_LENGTH; + + if ((result = fs_readlink(ns, dummy, path, &pathLen)) < B_OK) + { + put_vnode(ns->nsid, *vnid); + return result; + } + + path[pathLen] = 0; + result = new_path(path, newpath); + + if (result < B_OK) + { + put_vnode(ns->nsid, *vnid); + return result; + } + + return put_vnode(ns->nsid, *vnid); + } + + return B_OK; +} + +// fs_opendir() +// +extern int fs_opendir(fs_nspace *ns, fs_node *node, btCookie **cookie) +{ + struct stat st; + status_t result; + +//dprintf("fs_opendir()\n"); + // Do a basic stat() on this file to verify we indeed have a directory. + // If we cannot obtain this information, we have an even bigger problem. + if ((result = btStat(ns, node->vnid, &st)) < B_OK) + return result; + + // Now that we have the right information, verify we're looking at a directory. + if (!S_ISDIR(st.st_mode)) + return ENOTDIR; + + // Allocate and initialize the cookie. + *cookie = (btCookie *) malloc(sizeof(btCookie)); + if (!*cookie) + return ENOMEM; + + memset((*cookie)->opaque, 0, BT_COOKIE_SIZE); + (*cookie)->lpbCache = false; + (*cookie)->eof = false; + + return B_OK; +} + +// fs_closedir() +// +extern int fs_closedir(fs_nspace *ns, fs_node *node, btCookie *cookie) +{ +//dprintf("fs_closedir()\n"); + btEmptyLPBCache(cookie); + return B_OK; +} + +// fs_rewinddir() +// +extern int fs_rewinddir(fs_nspace *ns, fs_node *node, btCookie *cookie) +{ +//dprintf("fs_rewinddir()\n"); + memset(cookie->opaque, 0, BT_COOKIE_SIZE); + cookie->eof = false; + btEmptyLPBCache(cookie); + return B_OK; +} + +// fs_readdir() +// +extern int fs_readdir(fs_nspace *ns, fs_node *node, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize) +{ + status_t result; + vnode_id vnid; + char *filename; + long max, bufContent; + int32 value; + +//dprintf("fs_readdir()\n"); + max = *num; + *num = 0; + + // Cause the directory to be read. + while ((result = btReadDir(ns, node->vnid, &vnid, &filename, cookie)) == B_OK) + { + if (strcmp(filename, ".") && strcmp(filename, "..")) + { + create_node(ns, node->vnid, filename, vnid, false); + +// dirCount = bufsize / sizeof(struct dirent); +// pktCount = BT_MAX_IO_BUFFER / sizeof(struct dirent); +// dirCount = min((), ()); + + bufContent = 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(filename) + 1; + if (bufsize < bufContent) + return B_OK; + + buf->d_dev = ns->nsid; + buf->d_pdev = ns->nsid; + buf->d_ino = vnid; + buf->d_pino = node->vnid; + buf->d_reclen = bufContent; + strcpy(buf->d_name, filename); + + bufsize -= bufContent; + buf = (struct dirent *)((char *) buf + bufContent); + + (*num)++; + } + + free(filename); + + if (*num == max) + return B_OK; + } + + return B_OK; +} + +// fs_free_dircookie() +// +extern int fs_free_dircookie(fs_nspace *ns, fs_node *node, btCookie *cookie) +{ +//dprintf("fs_free_dircookie()\n"); + if (cookie) + { + btEmptyLPBCache(cookie); + free(cookie); + } + + return B_OK; +} + +// fs_rstat() +// +extern int fs_rstat(fs_nspace *ns, fs_node *node, struct stat *st) +{ + status_t result; + +//dprintf("fs_rstat()\n"); + if ((result = btStat(ns, node->vnid, st)) < B_OK) + return result; + + st->st_dev = ns->nsid; + return B_OK; +} + +// fs_mount() +// +extern int fs_mount(nspace_id nsid, const char *devname, ulong flags, struct mount_bt_params *parms, size_t len, fs_nspace **data, vnode_id *vnid) +{ + status_t result; + fs_nspace *ns; + fs_node *rootNode; + struct stat st; + + result = EINVAL; + +dprintf("fs_mount running\n"); + // If we didn't receive any mount parameters, we won't know the server to connect to, + // or the folder to be shared. + if (parms == NULL) + return EINVAL; + + // Initialize the ksocket library for kernel-based network communication. +#ifndef BONE_VERSION + if ((result = ksocket_init()) < B_OK) + return result; +#else + if (!bone_init()) + return ENETUNREACH; +#endif + +dprintf("net initialized\n"); + // Allocate our private file system information block. + ns = (fs_nspace *) malloc(sizeof(fs_nspace)); + ns->nsid = nsid; + ns->dnlcRoot = NULL; + + // Copy over the parameters specified, including the server, folder, user and group + // IDs, and so on. + ns->params.serverIP = parms->serverIP; + ns->params.server = strdup(parms->server); + ns->params.export = strdup(parms->export); + ns->params.uid = parms->uid; + ns->params.gid = parms->gid; + ns->params.hostname = strdup(parms->hostname); + ns->params.folder = strdup(parms->folder); + + // The password is a binary token that is of fixed length, but can contain null characters. + // A strdup() therefore won't capture the entire string. Manually copying the data is the + // only reliable way. + strcpy(ns->params.user, parms->user); + memcpy(ns->params.password, parms->password, BT_AUTH_TOKEN_LENGTH); + ns->params.password[BT_AUTH_TOKEN_LENGTH] = 0; + + // Now connect to the remote server. The socket returned will be used for all future + // communication with that server. + ns->s = btConnect(ns, ns->params.serverIP, BT_TCPIP_PORT); + if (ns->s != INVALID_SOCKET) + { + dprintf("connection established\n"); + ns->xid = 0; + + btRPCInit(ns); + + // Create a semaphore for exclusive access to the vnode list when we need to scan + // for a particular vnode. + ns->sem = create_sem(1, "VNode List Semaphore"); + if (ns->sem > 0) + { + dprintf("vnode semaphore created\n"); + if (initManagedData(&ns->dnlcData)) + { + dprintf("managed data struct initialized\n"); + // The system should own this semaphore. + set_sem_owner(ns->sem, B_SYSTEM_TEAM); + + // Allocate the root node. + rootNode = (fs_node *) malloc(sizeof(fs_node)); + rootNode->next = NULL; + + // Let the server know we are mounting the exported folder. This operation + // will return the root node file handle. + result = btMount(ns, ns->params.export, ns->params.user, ns->params.password, &rootNode->vnid); + if (result == B_OK) + { + ns->rootid = rootNode->vnid; + *vnid = ns->rootid; + + result = new_vnode(nsid, *vnid, rootNode); + if (result == B_OK) + { + *data = ns; + ns->first = rootNode; + notify_listener(B_DEVICE_MOUNTED, ns->nsid, 0, 0, 0, NULL); + dprintf("Mount successful."); + return B_OK; + } + } + else dprintf("Mount failed %d\n", result); + + // We've failed. The first step is to free the root node we allocated, and + // release the semaphore we created as well. + free(rootNode); + closeManagedData(&ns->dnlcData); + } + + delete_sem(ns->sem); + } + + // Disconnect from the server. + btDisconnect(ns); + btRPCClose(ns); + } + else + result = EHOSTUNREACH; + + // De-allocate our private file system structure and all the string space we duplicated + // on startup. + free(ns->params.hostname); + free(ns->params.folder); + free(ns->params.export); + free(ns->params.server); + free(ns); + +#ifndef BONE_VERSION + ksocket_cleanup(); +#else + bone_cleanup(); +#endif + + return result; +} + +extern int fs_unmount(fs_nspace *ns) +{ +//dprintf("fs_unmount()\n"); + notify_listener(B_DEVICE_UNMOUNTED, ns->nsid, 0, 0, 0, NULL); + + btDisconnect(ns); + btRPCClose(ns); + + free(ns->params.hostname); + free(ns->params.folder); + free(ns->params.export); + free(ns->params.server); + + while (acquire_sem(ns->sem) == B_INTERRUPTED); + + while (ns->first) + { + fs_node *next = ns->first->next; + free(ns->first); + ns->first = next; + } + + release_sem(ns->sem); + delete_sem(ns->sem); + + ns->s = INVALID_SOCKET; + free(ns); + +#ifndef BONE_VERSION + ksocket_cleanup(); +#else + bone_cleanup(); +#endif + + return B_OK; +} + +// fs_rfsstat() +// +extern int fs_rfsstat(fs_nspace *ns, struct fs_info *info) +{ + bt_fsinfo fsinfo; + int result; + +//dprintf("fs_rfsstat()\n"); + result = btGetFSInfo(ns, ns->rootid, &fsinfo); + if (result == B_OK) + { + info->dev = ns->nsid; + info->root = ns->rootid; + info->flags = B_FS_IS_SHARED | B_FS_IS_PERSISTENT | + B_FS_HAS_MIME | B_FS_HAS_ATTR | B_FS_HAS_QUERY; + info->block_size = fsinfo.blockSize; + info->io_size = 8192; + info->total_blocks = fsinfo.totalBlocks; + info->free_blocks = fsinfo.freeBlocks; + info->total_nodes = 0; + info->free_nodes = 0; + strcpy(info->device_name, "BeServed Shared Volume"); + strcpy(info->volume_name, ns->params.folder); + strcpy(info->fsh_name, ""); + } + + return result; +} + +// fs_open() +// +extern int fs_open(fs_nspace *ns, fs_node *node, int omode, fs_file_cookie **cookie) +{ + struct stat st; + status_t result; + +//dprintf("fs_open()\n"); + if ((result = btStat(ns, node->vnid, &st)) < B_OK) + return result; + + if (S_ISDIR(st.st_mode)) + { + *cookie = NULL; + return B_OK; // permit opening of directories + } + + *cookie = (fs_file_cookie *) malloc(sizeof(fs_file_cookie)); + (*cookie)->omode = omode; + (*cookie)->original_size = st.st_size; + (*cookie)->st = st; + + return B_OK; +} + +// fs_close() +// +extern int fs_close(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie) +{ +//dprintf("fs_close()\n"); + if (cookie && (cookie->omode & O_RDWR || cookie->omode & O_WRONLY)) + return notify_listener(B_STAT_CHANGED, ns->nsid, 0, 0, node->vnid, NULL); + + return B_OK; +} + +// fs_free_cookie() +// +extern int fs_free_cookie(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie) +{ +//dprintf("fs_free_cookie()\n"); + if (cookie) + free(cookie); + + return B_OK; +} + +// fs_read() +// +extern int fs_read(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, void *buf, size_t *len) +{ +//dprintf("fs_read()\n"); + if (!len) + return B_ERROR; + + // If we weren't given proper file system or vnode pointers, something is awry. + if (!ns || !node || !buf) + return B_ERROR; + + // Do not permit reading directories. + if (!cookie) + return EISDIR; + + *len = btRead(ns, node->vnid, pos, *len, buf); + + return B_OK; +} + +extern int fs_write(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, const void *buf, size_t *len) +{ +//dprintf("fs_write()\n"); + // Do not permit writing directories. + if (!cookie) + return EISDIR; + + if (cookie->omode & O_APPEND) + pos += cookie->original_size; + + *len = btWrite(ns, node->vnid, pos, *len, buf); + btStat(ns, node->vnid, &cookie->st); + + return B_OK; +} + +extern int fs_wstat(fs_nspace *ns, fs_node *node, struct stat *st, long mask) +{ + int error; + +//dprintf("fs_wstat()\n"); + error = btWStat(ns, node->vnid, st, mask); + if (error != B_OK) + return error; + + return notify_listener(B_STAT_CHANGED, ns->nsid, 0, 0, node->vnid, NULL); +} + +extern int fs_wfsstat(fs_nspace *ns, struct fs_info *info, long mask) +{ +//dprintf("fs_wfsstat()\n"); + return B_OK; +} + +extern int fs_create(fs_nspace *ns, fs_node *dir, const char *name, int omode, int perms, vnode_id *vnid, + fs_file_cookie **cookie) +{ + struct stat st; + status_t result; + int error; + +//dprintf("fs_create()\n"); + result = btLookup(ns, dir->vnid, name, vnid, &st); + + if (result == B_OK) + { + void *dummy; + create_node(ns, dir->vnid, name, *vnid, false); + + if ((result = get_vnode(ns->nsid, *vnid, (void **) &dummy)) < B_OK) + return result; + + if (S_ISDIR(st.st_mode)) + return EISDIR; + + if (omode & O_EXCL) + return EEXIST; + + if (omode & O_TRUNC) + if ((result = btTruncate(ns, *vnid, 0L)) < B_OK) + return result; + + *cookie = (fs_file_cookie *) malloc(sizeof(fs_file_cookie)); + (*cookie)->omode = omode; + (*cookie)->original_size = st.st_size; + (*cookie)->st = st; + + return B_OK; + } + else if (result != ENOENT) + return result; + else + { + uint8 *replyBuf; + int32 status; + fs_node *newNode; + + if (!(omode & O_CREAT)) + return ENOENT; + + error = btCreate(ns, dir->vnid, name, vnid, omode, perms, &st); + if (error != B_OK) + return error; + + newNode = create_node(ns, dir->vnid, name, *vnid, true); + + *cookie = (fs_file_cookie *) malloc(sizeof(fs_file_cookie)); + (*cookie)->omode = omode; + (*cookie)->original_size = st.st_size; + (*cookie)->st = st; + + return notify_listener(B_ENTRY_CREATED, ns->nsid, dir->vnid, 0, *vnid, name); + } +} + +extern int fs_unlink(fs_nspace *ns, fs_node *dir, const char *name) +{ + fs_node *newNode; + fs_node *dummy; + struct stat st; + vnode_id vnid; + int error; + +//dprintf("fs_unlink()\n"); + error = btLookup(ns, dir->vnid, name, &vnid, &st); + if (error != B_OK) + return error; + + create_node(ns, dir->vnid, name, vnid, false); + + error = get_vnode(ns->nsid, vnid, (void **) &dummy); + if (error != B_OK) + return error; + + if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) + return EISDIR; + + error = remove_vnode(ns->nsid, vnid); + if (error != B_OK) + return error; + + error = put_vnode(ns->nsid, vnid); + if (error != B_OK) + return error; + + error = btUnlink(ns, dir->vnid, name); + if (error != B_OK) + return error; + + return notify_listener(B_ENTRY_REMOVED, ns->nsid, dir->vnid, 0, vnid, name); +} + +extern int fs_remove_vnode(fs_nspace *ns, fs_node *node, char r) +{ +//dprintf("fs_remove_vnode()\n"); + remove_node(ns, node->vnid); + return B_OK; +} + +// fs_secure_vnode() +// +// Description: Given a node, this function determines whether the user has the +// required permission to access it. This is currently unimplemented in BFS, and +// we consequently dismiss it here as well. +// +extern int fs_secure_vnode(fs_nspace *ns, fs_node *node) +{ +//dprintf("fs_secure_vnode()\n"); + return B_OK; +} + +extern int fs_mkdir(fs_nspace *ns, fs_node *dir, const char *name, int perms) +{ + fs_node *newNode; + struct stat st; + vnode_id vnid; + int error; + +//dprintf("fs_mkdir()\n"); + error = btLookup(ns, dir->vnid, name, &vnid, &st); + if (error == B_OK) + { + void *dummy; + error = get_vnode(ns->nsid, vnid, (void **) &dummy); + if (error != B_OK) + return error; + + return EEXIST; + } + else if (error != ENOENT) + return error; + + error = btCreateDir(ns, dir->vnid, name, perms | S_IFDIR, &vnid, &st); + if (error != B_OK) + return error; + + create_node(ns, dir->vnid, name, vnid, false); + return notify_listener(B_ENTRY_CREATED, ns->nsid, dir->vnid, 0, vnid, name); +} + +extern int fs_rename(fs_nspace *ns, fs_node *olddir, const char *oldname, fs_node *newdir, const char *newname) +{ + struct stat st; + fs_node *oldNode; + vnode_id vnid; + int error; + +//dprintf("fs_rename()\n"); + error = btLookup(ns, newdir->vnid, newname, &vnid, &st); + if (error == B_OK) + { + if (S_ISREG(st.st_mode)) + error = fs_unlink(ns, newdir, newname); + else + error = fs_rmdir(ns, newdir, newname); + + if (error != B_OK) + return error; + } + + error = btLookup(ns, olddir->vnid, oldname, &vnid, &st); + if (error != B_OK) + return error; + + error = btRename(ns, olddir->vnid, oldname, newdir->vnid, newname); + if (error != B_OK) + return error; + + rename_node(ns, olddir->vnid, oldname, newdir->vnid, newname, vnid); + + return notify_listener(B_ENTRY_MOVED, ns->nsid, olddir->vnid, newdir->vnid, vnid, newname); +} + +extern int fs_rmdir(fs_nspace *ns, fs_node *dir, const char *name) +{ + fs_node *newNode; + fs_node *dummy; + vnode_id vnid; + struct stat st; + int error; + +//dprintf("fs_rmdir()\n"); + error = btLookup(ns, dir->vnid, name, &vnid, &st); + if (error != B_OK) + return error; + + create_node(ns, dir->vnid, name, vnid, false); + + error = get_vnode(ns->nsid, vnid, (void **) &dummy); + if (error != B_OK) + return error; + + if (!S_ISDIR(st.st_mode)) + return ENOTDIR; + + error = remove_vnode(ns->nsid, vnid); + if (error != B_OK) + return error; + + error = put_vnode(ns->nsid, vnid); + if (error != B_OK) + return error; + + error = btDeleteDir(ns, dir->vnid, name); + if (error != B_OK) + return error; + + return notify_listener(B_ENTRY_REMOVED, ns->nsid, dir->vnid, 0, vnid, name); +} + +extern int fs_readlink(fs_nspace *ns, fs_node *node, char *buf, size_t *bufsize) +{ +//dprintf("fs_readlink()\n"); + return btReadLink(ns, node->vnid, buf, bufsize); +} + +extern int fs_symlink(fs_nspace *ns, fs_node *dir, const char *name, const char *path) +{ + struct stat st; + vnode_id vnid; + int error; + +//dprintf("fs_symlink()\n"); + error = btLookup(ns, dir->vnid, name, &vnid, &st); + if (error == B_OK) + { + void *dummy; + if ((error = get_vnode(ns->nsid, vnid, (void **) &dummy)) < B_OK) + return error; + + return EEXIST; + } + else if (error != ENOENT) + return error; + + error = btSymLink(ns, dir->vnid, name, path); + if (error != B_OK) + return error; + + error = btLookup(ns, dir->vnid, name, &vnid, &st); + if (error != B_OK) + return error; + + create_node(ns, dir->vnid, name, vnid, false); + + error = notify_listener(B_ENTRY_CREATED, ns->nsid, dir->vnid, 0, vnid, name); + return error; +} + +// fs_access() +// +// Description: This function implements the access() system call. +// +int fs_access(void *ns, void *node, int mode) +{ +//dprintf("fs_access()\n"); + return B_OK; +} + +int fs_read_attrib(fs_nspace *ns, fs_node *node, const char *name, int type, void *buf, size_t *len, off_t pos) +{ + int bytes; + + // Automatically deny reading Tracker attributes. +//dprintf("fs_read_attrib()\n"); + if (strncmp(name, "_trk/", 5) == 0) + { + errno = B_ENTRY_NOT_FOUND; + return -1; + } + + bytes = btReadAttrib(ns, node->vnid, name, type, buf, *len, pos); + if (bytes == -1) + return -1; + + *len = bytes; + return B_OK; +} + +int fs_write_attrib(fs_nspace *ns, fs_node *node, const char *name, int type, const void *buf, size_t *len, off_t pos) +{ + int bytes; + +//dprintf("fs_write_attrib()\n"); + // Automatically deny reading Tracker attributes. + if (strncmp(name, "_trk/", 5) == 0) + { + errno = B_ENTRY_NOT_FOUND; + return -1; + } + + bytes = btWriteAttrib(ns, node->vnid, name, type, buf, *len, pos); + if (bytes == -1) + return -1; + + *len = bytes; + notify_listener(B_ATTR_CHANGED, ns->nsid, 0, 0, node->vnid, node->name); + return B_OK; +} + +// fs_open_attribdir() +// +extern int fs_open_attribdir(fs_nspace *ns, fs_node *node, btCookie **cookie) +{ + struct stat st; + int error; + +//dprintf("fs_open_attribdir()\n"); + // Do a basic stat() on this file to verify we indeed have a valid file. + // If we cannot obtain this information, we have an even bigger problem. + if ((error = btStat(ns, node->vnid, &st)) < B_OK) + return error; + + // Allocate and initialize the cookie. + *cookie = (btCookie *) malloc(sizeof(btCookie)); + if (!*cookie) + return ENOMEM; + + memset((*cookie)->opaque, 0, BT_COOKIE_SIZE); + (*cookie)->lpbCache = false; + (*cookie)->eof = false; + + return B_OK; +} + +// fs_close_attribdir() +// +extern int fs_close_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie) +{ +//dprintf("fs_close_attribdir()\n"); + btEmptyLPBCache(cookie); + return B_OK; +} + +// fs_rewind_attribdir() +// +extern int fs_rewind_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie) +{ +//dprintf("fs_rewind_attribdir()\n"); + if (cookie) + { + memset(cookie->opaque, 0, BT_COOKIE_SIZE); + btEmptyLPBCache(cookie); + cookie->eof = false; + } + + return B_OK; +} + +extern int fs_read_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize) +{ + status_t result; + char *attrName; + long max; + +//dprintf("fs_read_attribdir()\n"); + max = *num; + *num = 0; + + // Cause the directory to be read. + while ((result = btReadAttribDir(ns, node->vnid, &attrName, cookie)) == B_OK) + { + if (strncmp(attrName, "_trk/", 5) != 0) + { + if (bufsize < 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(attrName) + 1) + return B_OK; + + buf->d_dev = 0; + buf->d_pdev = 0; + buf->d_ino = 0; + buf->d_pino = 0; + buf->d_reclen = 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(attrName) + 1; + strcpy(buf->d_name, attrName); + + bufsize -= buf->d_reclen; + buf = (struct dirent *)((char *) buf + buf->d_reclen); + + (*num)++; + } + + free(attrName); + + if (*num == max) + break; + } + + return B_OK; +} + +// fs_free_attribdircookie() +// +extern int fs_free_attribdircookie(fs_nspace *ns, btCookie *cookie) +{ +//dprintf("fs_free_attribdircookie()\n"); +// if (cookie) +// { +// btEmptyLPBCache(cookie); +// free(cookie); +// } + + return B_OK; +} + +// fs_remove_attrib() +// +extern int fs_remove_attrib(fs_nspace *ns, fs_node *node, const char *name) +{ +//dprintf("fs_remove_attrib()\n"); + // Automatically deny removing Tracker attributes. + if (strncmp(name, "_trk/", 5) == 0) + { + errno = B_ENTRY_NOT_FOUND; + return -1; + } + + return btRemoveAttrib(ns, node->vnid, name); +} + +// fs_stat_attrib() +// +extern int fs_stat_attrib(fs_nspace *ns, fs_node *node, const char *name, struct attr_info *buf) +{ + buf->type = 0; + buf->size = 0; + +//dprintf("fs_stat_attrib()\n"); + // Automatically deny reading Tracker attributes. + if (strncmp(name, "_trk/", 5) == 0) + { + errno = B_ENTRY_NOT_FOUND; + return -1; + } + + return btStatAttrib(ns, node->vnid, name, buf); +} + +// fs_open_indexdir() +// +extern int fs_open_indexdir(fs_nspace *ns, btCookie **cookie) +{ +//dprintf("fs_open_indexdir()\n"); + // Allocate and initialize the cookie. + *cookie = (btCookie *) malloc(sizeof(btCookie)); + memset ((*cookie)->opaque, 0, BT_COOKIE_SIZE); + (*cookie)->eof = false; + + return B_OK; +} + +// fs_close_indexdir() +// +extern int fs_close_indexdir(fs_nspace *ns, btCookie *cookie) +{ +//dprintf("fs_close_indexdir()\n"); + return B_OK; +} + +// fs_rewind_indexdir() +// +extern int fs_rewind_indexdir(fs_nspace *ns, btCookie *cookie) +{ +//dprintf("fs_rewind_indexdir()\n"); + memset(cookie->opaque, 0, BT_COOKIE_SIZE); + cookie->eof = false; + return B_OK; +} + +// fs_read_indexdir() +// +extern int fs_read_indexdir(fs_nspace *ns, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize) +{ + status_t result; + char indexName[100]; + long max; + +//dprintf("fs_read_indexdir()\n"); + max = *num; + *num = 0; + + // Cause the directory to be read. + while ((result = btReadIndexDir(ns, indexName, sizeof(indexName) - 1, cookie)) == B_OK) + { + if (bufsize < 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(indexName) + 1) + return B_OK; + + buf->d_dev = 0; + buf->d_pdev = 0; + buf->d_ino = 0; + buf->d_pino = 0; + buf->d_reclen = 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(indexName) + 1; + strcpy(buf->d_name, indexName); + + bufsize -= buf->d_reclen; + buf = (struct dirent *)((char *) buf + buf->d_reclen); + + (*num)++; + + if (*num == max) + return B_OK; + } + + return B_OK; +} + +// fs_free_indexdircookie() +// +extern int fs_free_indexdircookie(fs_nspace *ns, btCookie *cookie) +{ +//dprintf("fs_free_indexdircookie()\n"); + if (cookie) + free(cookie); + + return B_OK; +} + +extern int fsCreateIndex(fs_nspace *ns, const char *name, int type, int flags) +{ +//dprintf("fs_create_index()\n"); + return btCreateIndex(ns, name, type, flags); +} + +extern int fsRemoveIndex(fs_nspace *ns, const char *name) +{ +//dprintf("fs_remove_index()\n"); + return btRemoveIndex(ns, name); +} + +extern int fsStatIndex(fs_nspace *ns, const char *name, struct index_info *buf) +{ +//dprintf("fs_stat_index()\n"); + buf->type = 0; + buf->size = 0; + buf->modification_time = 0; + buf->creation_time = 0; + buf->uid = 0; + buf->gid = 0; + + return btStatIndex(ns, name, buf); +} + +extern int fsOpenQuery(fs_nspace *ns, const char *query, ulong flags, port_id port, long token, btQueryCookie **cookie) +{ +//dprintf("fs_openquery()\n"); + // Allocate and initialize the cookie. + *cookie = (btQueryCookie *) malloc(sizeof(btQueryCookie)); + memset ((*cookie)->opaque, 0, BT_COOKIE_SIZE); + (*cookie)->query = strdup(query); + + return B_OK; +} + +extern int fsCloseQuery(fs_nspace *ns, btQueryCookie *cookie) +{ +//dprintf("fs_closequery()\n"); + return B_OK; +} + +extern int fsReadQuery(fs_nspace *ns, btQueryCookie *cookie, long *num, struct dirent *buf, size_t bufsize) +{ + char *filename; + vnode_id vnid, parent; + long max, bufContent; + +//dprintf("fs_readquery()\n"); + max = *num; + *num = 0; + + while (btReadQuery(ns, &filename, &vnid, &parent, cookie) == B_OK) + { + bufContent = 2 * (sizeof(dev_t) + sizeof(ino_t)) + sizeof(unsigned short) + strlen(filename) + 1; + if (bufsize < bufContent) + return B_OK; + + buf->d_dev = ns->nsid; + buf->d_pdev = ns->nsid; + buf->d_ino = vnid; + buf->d_pino = parent; + buf->d_reclen = bufContent; + strcpy(buf->d_name, filename); + + bufsize -= bufContent; + buf = (struct dirent *)((char *) buf + bufContent); + + free(filename); + + (*num)++; + if (*num == max) + break; + } + + return B_OK; +} + +extern int fsFreeQueryCookie(fs_nspace *ns, btQueryCookie *cookie) +{ +//dprintf("fs_freequerycookie()\n"); + if (cookie) + { + if (cookie->query) + free(cookie->query); + + free(cookie); + } + + return B_OK; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/nfs_add_on.h b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/nfs_add_on.h new file mode 100644 index 0000000000..ce48633442 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/nfs_add_on.h @@ -0,0 +1,173 @@ +#ifndef _NFS_ADD_ON_H +#define _NFS_ADD_ON_H + +#ifndef _IMPEXP_KERNEL +#define _IMPEXP_KERNEL +#endif + +#include "fsproto.h" +#include "betalk.h" +#include "readerWriter.h" + +#include +#include +#include + +struct mount_bt_params +{ + unsigned int serverIP; + char *server; + char *export; + uid_t uid; + gid_t gid; + char *hostname; + char *folder; + char user[MAX_USERNAME_LENGTH + 1]; + char password[BT_AUTH_TOKEN_LENGTH * 2 + 1]; +}; + +struct fs_node +{ + vnode_id parent; + vnode_id vnid; + char name[B_FILE_NAME_LENGTH + 1]; + struct fs_node *next; +}; + +typedef struct dnlcEntry +{ + time_t entryTime; + struct stat st; + vnode_id vnid; + vnode_id parent; + char name[B_FILE_NAME_LENGTH]; + struct dnlcEntry *next, *prev; +} dnlc_entry; + +struct fs_nspace +{ + nspace_id nsid; + + thread_id tid; + bool quit; + + struct sockaddr_in mountAddr, nfsAddr; + uint32 serverIP; + int32 serverPort; + int s; + + thread_id rpcThread; + int32 xid; + int32 quitXID; + + vnode_id rootid; + sem_id sem; + struct fs_node *first; + + dnlc_entry *dnlcRoot; + bt_managed_data dnlcData; + + struct mount_bt_params params; +}; + +struct fs_file_cookie +{ + int omode; + off_t original_size; + struct stat st; +}; + +typedef struct fs_nspace fs_nspace; +typedef struct fs_node fs_node; +typedef struct fs_file_cookie fs_file_cookie; + +int fs_read_vnode(fs_nspace *ns, vnode_id vnid, char r, fs_node **node); +int fs_write_vnode(fs_nspace *ns, fs_node *node, char r); + +int fs_walk(fs_nspace *ns, fs_node *base, const char *file, char **newpath, + vnode_id *vnid); + +int fs_opendir(fs_nspace *ns, fs_node *node, btCookie **cookie); +int fs_closedir(fs_nspace *ns, fs_node *node, btCookie *cookie); +int fs_rewinddir(fs_nspace *ns, fs_node *node, btCookie *cookie); +int fs_readdir(fs_nspace *ns, fs_node *node, btCookie *cookie, long *num, + struct dirent *buf, size_t bufsize); + +int fs_free_dircookie(fs_nspace *ns, fs_node *node, btCookie *cookie); +int fs_rstat(fs_nspace *ns, fs_node *node, struct stat *); +int fs_mount(nspace_id nsid, const char *devname, ulong flags, + struct mount_bt_params *parms, size_t len, fs_nspace **data, vnode_id *vnid); +int fs_unmount(fs_nspace *ns); +int fs_rfsstat(fs_nspace *ns, struct fs_info *); + +int fs_open(fs_nspace *ns, fs_node *node, int omode, fs_file_cookie **cookie); +int fs_close(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie); +int fs_free_cookie(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie); +int fs_read(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, void *buf, + size_t *len); + +int fs_write(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, + const void *buf, size_t *len); + +int fs_wstat(fs_nspace *ns, fs_node *node, struct stat *, long mask); +int fs_wfsstat(fs_nspace *ns, struct fs_info *, long mask); +int fs_create(fs_nspace *ns, fs_node *dir, const char *name, + int omode, int perms, vnode_id *vnid, fs_file_cookie **cookie); + +int fs_unlink(fs_nspace *ns, fs_node *dir, const char *name); +int fs_remove_vnode(fs_nspace *ns, fs_node *node, char r); +int fs_secure_vnode(fs_nspace *ns, fs_node *node); + +int fs_mkdir(fs_nspace *ns, fs_node *dir, const char *name, int perms); + +int fs_rename(fs_nspace *ns, fs_node *olddir, const char *oldname, + fs_node *newdir, const char *newname); + +int fs_rmdir(fs_nspace *ns, fs_node *dir, const char *name); +int fs_readlink(fs_nspace *ns, fs_node *node, char *buf, size_t *bufsize); + +int fs_symlink(fs_nspace *ns, fs_node *dir, const char *name, + const char *path); + +fs_node *create_node(fs_nspace *ns, vnode_id dir_vnid, const char *name, vnode_id file_vnid, bool newVnid); +fs_node *getDuplicateVnid(fs_nspace *ns, vnode_id vnid); +fs_node *getDuplicateName(fs_nspace *ns, vnode_id parent, const char *name); +void remove_obsolete_node(fs_nspace *ns, fs_node *node); +void rename_node(fs_nspace *ns, vnode_id old_dir_vnid, const char *oldname, vnode_id new_dir_vnid, const char *newname, vnode_id file_vnid); +void remove_node(fs_nspace *ns, vnode_id vnid); +void print_vnode_list(fs_nspace *ns); + +extern int fs_access(void *ns, void *node, int mode); + +extern int fs_read_attrib(fs_nspace *ns, fs_node *node, const char *name, int type, void *buf, size_t *len, off_t pos); +extern int fs_write_attrib(fs_nspace *ns, fs_node *node, const char *name, int type, const void *buf, size_t *len, off_t pos); +extern int fs_open_attribdir(fs_nspace *ns, fs_node *node, btCookie **cookie); +extern int fs_close_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie); +extern int fs_rewind_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie); +extern int fs_read_attribdir(fs_nspace *ns, fs_node *node, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize); +extern int fs_free_attribdircookie(fs_nspace *ns, btCookie *cookie); +extern int fs_remove_attrib(fs_nspace *ns, fs_node *node, const char *name); +extern int fs_stat_attrib(fs_nspace *ns, fs_node *node, const char *name, struct attr_info *buf); + +extern int fs_open_indexdir(fs_nspace *ns, btCookie **cookie); +extern int fs_close_indexdir(fs_nspace *ns, btCookie *cookie); +extern int fs_rewind_indexdir(fs_nspace *ns, btCookie *cookie); +extern int fs_read_indexdir(fs_nspace *ns, btCookie *cookie, long *num, struct dirent *buf, size_t bufsize); +extern int fs_free_indexdircookie(fs_nspace *ns, btCookie *cookie); +extern int fsCreateIndex(fs_nspace *ns, const char *name, int type, int flags); +extern int fsRemoveIndex(fs_nspace *ns, const char *name); +extern int fsStatIndex(fs_nspace *ns, const char *name, struct index_info *buf); + +extern int fsOpenQuery(fs_nspace *ns, const char *query, ulong flags, port_id port, long token, btQueryCookie **cookie); +extern int fsCloseQuery(fs_nspace *ns, btQueryCookie *cookie); +extern int fsReadQuery(fs_nspace *ns, btQueryCookie *cookie, long *num, struct dirent *buf, size_t bufsize); +extern int fsFreeQueryCookie(fs_nspace *ns, btQueryCookie *cookie); + +enum +{ + C_ERROR_STALE=B_ERRORS_END+1 +}; + +#define USE_SYSTEM_AUTHENTICATION 1 + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/readerWriter.c b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/readerWriter.c new file mode 100644 index 0000000000..32a3774858 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/readerWriter.c @@ -0,0 +1,133 @@ +// readerWriter.c + +#include "betalk.h" +#include "readerWriter.h" + + +void btLock(sem_id semaphore, int32 *atomic) +{ + int32 previous = atomic_add(atomic, 1); + if (previous >= 1) + while (acquire_sem(semaphore) == B_INTERRUPTED); +} + +void btUnlock(sem_id semaphore, int32 *atomic) +{ + int32 previous = atomic_add(atomic, -1); + if (previous > 1) + release_sem(semaphore); +} + +bool initManagedData(bt_managed_data *data) +{ + data->readCount = 0; + data->writeCount = 0; + + data->readCountVar = 0; + data->writeCountVar = 0; + data->readerQueueVar = 0; + data->readerVar = 0; + data->writerVar = 0; + + if ((data->readCountSem = create_sem(1, "Read Counter")) < 0) + return false; + + if ((data->writeCountSem = create_sem(1, "Write Counter")) < 0) + { + delete_sem(data->readCountSem); + return false; + } + + if ((data->readerQueue = create_sem(1, "Read Queue")) < 0) + { + delete_sem(data->writeCountSem); + delete_sem(data->readCountSem); + return false; + } + + if ((data->reader = create_sem(1, "Single Reader")) < 0) + { + delete_sem(data->readerQueue); + delete_sem(data->writeCountSem); + delete_sem(data->readCountSem); + return false; + } + + if ((data->writer = create_sem(1, "Writer")) < 0) + { + delete_sem(data->reader); + delete_sem(data->readerQueue); + delete_sem(data->writeCountSem); + delete_sem(data->readCountSem); + return false; + } + + set_sem_owner(data->readCountSem, B_SYSTEM_TEAM); + set_sem_owner(data->writeCountSem, B_SYSTEM_TEAM); + set_sem_owner(data->readerQueue, B_SYSTEM_TEAM); + set_sem_owner(data->reader, B_SYSTEM_TEAM); + set_sem_owner(data->writer, B_SYSTEM_TEAM); + + return true; +} + +void closeManagedData(bt_managed_data *data) +{ + data->readCount = data->writeCount = 0; + + delete_sem(data->writer); + delete_sem(data->reader); + delete_sem(data->readerQueue); + delete_sem(data->writeCountSem); + delete_sem(data->readCountSem); +} + +void beginReading(bt_managed_data *data) +{ + btLock(data->readerQueue, &data->readerQueueVar); + btLock(data->reader, &data->readerVar); + btLock(data->readCountSem, &data->readCountVar); + + data->readCount++; + if (data->readCount == 1) + btLock(data->writer, &data->writerVar); + + btUnlock(data->readCountSem, &data->readCountVar); + btUnlock(data->reader, &data->readerVar); + btUnlock(data->readerQueue, &data->readerQueueVar); +} + +void endReading(bt_managed_data *data) +{ + btLock(data->readCountSem, &data->readCountVar); + + data->readCount--; + if (data->readCount == 0) + btUnlock(data->writer, &data->writerVar); + + btUnlock(data->readCountSem, &data->readCountVar); +} + +void beginWriting(bt_managed_data *data) +{ + btLock(data->writeCountSem, &data->writeCountVar); + + data->writeCount++; + if (data->writeCount == 1) + btLock(data->reader, &data->readerVar); + + btUnlock(data->writeCountSem, &data->writeCountVar); + btLock(data->writer, &data->writerVar); +} + +void endWriting(bt_managed_data *data) +{ + btUnlock(data->writer, &data->writerVar); + btLock(data->writeCountSem, &data->writeCountVar); + + data->writeCount--; + if (data->writeCount == 0) + btUnlock(data->reader, &data->readerVar); + + btUnlock(data->writeCountSem, &data->writeCountVar); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/readerWriter.h b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/readerWriter.h new file mode 100644 index 0000000000..53b1ac117f --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/readerWriter.h @@ -0,0 +1,36 @@ +// readerWriter.h + +#include "betalk.h" + +typedef struct managedData +{ + int32 readCount; + int32 writeCount; + + // These two semaphores control access to the readCount and writeCount + // variables. + sem_id readCountSem; + int32 readCountVar; + sem_id writeCountSem; + int32 writeCountVar; + + // The first process wishes to gain read access blocks on the reader + // semaphore, but all other block on the readerQueue, so that writers + // can effectively jump the queue. + sem_id readerQueue; + int32 readerQueueVar; + + // Semaphores for holding waiting processes. + sem_id reader; + int32 readerVar; + sem_id writer; + int32 writerVar; +} bt_managed_data; + + +bool initManagedData(bt_managed_data *data); +void closeManagedData(bt_managed_data *data); +void beginReading(bt_managed_data *data); +void endReading(bt_managed_data *data); +void beginWriting(bt_managed_data *data); +void endWriting(bt_managed_data *data); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/sysdepdefs.h b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/sysdepdefs.h new file mode 100644 index 0000000000..a36586afb3 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/bt_fs/sysdepdefs.h @@ -0,0 +1,19 @@ +#ifndef _SYSDEPDEFS_H_ +#define _SYSDEPDEFS_H_ + +#ifdef BONE_VERSION + +#include + +//extern struct bone_socket_info *bone_module; + +#define closesocket(s) close(s) +#define kclosesocket(s) close(s) +#define ksend(s, buf, len, flg) bone_module->send(s, buf, len, flg) +#define krecv(s, buf, len, flg) bone_module->recv(s, buf, len, flg) +#define ksocket(fam, type, prot) bone_module->socket(fam, type, prot) +#define kconnect(s, addr, len) bone_module->connect(s, addr, len) +#define ksetsockopt(s, type, opt, flag, len) bone_module->setsockopt(s, type, opt, flag, len) +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/access.htm b/src/tests/add-ons/kernel/file_systems/beserved/documentation/access.htm new file mode 100644 index 0000000000..d349a1872c --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/documentation/access.htm @@ -0,0 +1,124 @@ + + + + + +BeServed File Access Instructions + + + + + + + + + + + + +


+ + + + + + + + +
  + + + + +
 Using the My Network Application
+ + + + +
+

+ The My Network application is installed by default into your applications folder. + It is used to view the computers on your network that are sharing their files using + BeServed.

+ To access the files on a remote computer, launch the My Network application by + double-clicking the icon in the applications folder. When the program appears, you + should see a list of the other computers on your network running the BeServed server. + If you do not see the computer(s) you expect, make sure it is running the server + application described in Sharing Your Files with Others.

+ Once you find the computer you're looking for, double-click its entry in the list + to display the list of shared folders that computer is making available. If you do + not see the shared folder you are looking for, check the settings on the remote + computer to ensure it is properly configured to share its files.

+ +

+ The My Network application is shown above. Several remote computers are + displayed. One computer is displayed with a fully qualified domain name, others have + simple host names, and one computer is shown with an IP address only. The address is + shown when a host name cannot be determined by consulting a DNS server or the local + /etc/hosts file.

+ +

+ Double-clicking on a specific computer opens another window displaying the folders + that are shared on that computer. The window above shows a single shared folder + called Linux Home Folders.

+ Once you have the shared folder you're looking for, double-click on it. That folder + will open in a Tracker window just as though the files were local to your machine. + At this point, you can browse through the remote file share using Tracker or the command + terminal. Aside from performance, it should be transparent that you are accessing files + on another computer.

+ If the remote computer has been configured to authenticate users against the BeSure + authentication server, you will be prompted for a user name and password before being + allowed to work with any of the files, and consequently, before the Tracker window + appears.

+ +

+ You can obtain information on any of the computers listed in the MyNetwork window, including + other names (aliases) that computer can be referenced by, the IP address(es) of the computer, + the type of hardware platform, the operating system, and number of active connections. To + view this information on a computer in the list, simply highlight the desired computer, then + click the About this Computer button.

+ +

+
+
  + + + + +
 Using Terminal
+ + + + +
+

+ You can also find computers and mount remote shared folders from the command line. + Two programs, lshosts and mounthost are provided for that purpose. + Both are installed in the BeOS shared bin folder (typically /boot/home/config/bin), + and should consequently be in your path.

+ To obtain a list of computers on your network running the BeServed server application, + type
lshosts
on the command line and press Enter. A list of computers will + be displayed by their network host name. The computers are listed in the order they + respond to your query. To view the shared folders exported on any host, simply append + the host name to the lshost command. For example, to view the shared folders on a + remote computer named "beos" you would type
lshosts beos

+ To mount a shared folder to a folder on your local computer, you use the mounthost command. + The syntax of this command is:

+
mounthost [-t] host:shared_folder [on] path

+ Example: +
mounthost beos:BootDir /boot/home/bootdir

+ The -t option is used only when the server you access requires authentication. + Normally, you will receive a simple prompt at the terminal window asking for your user name, + then your password. However, if you are using the mounthost command from within a shell + script, you may not have a terminal window in which to type. In this case, using the -t + option displays the Tracker login panel displayed above.
+
+
+
 
+ +

Copyright © 2001 Teldar Corporation. + All rights reserved.
+ If you experience difficulties using this site, please contact webmaster@teldar.com.

+
+ + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/AboutComputer.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/AboutComputer.jpg new file mode 100644 index 0000000000..093658da08 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/AboutComputer.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/AboutComputer_thm.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/AboutComputer_thm.jpg new file mode 100644 index 0000000000..8ff14c7e76 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/AboutComputer_thm.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureHosts.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureHosts.jpg new file mode 100644 index 0000000000..89f00a0145 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureHosts.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureHosts_thm.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureHosts_thm.jpg new file mode 100644 index 0000000000..99f5548183 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureHosts_thm.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureUsers.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureUsers.jpg new file mode 100644 index 0000000000..7ff47981b5 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureUsers.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureUsers_thm.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureUsers_thm.jpg new file mode 100644 index 0000000000..a5ea312e36 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/BeSureUsers_thm.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/DomainUsers.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/DomainUsers.jpg new file mode 100644 index 0000000000..b0f0fd10ee Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/DomainUsers.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/DomainUsers_thm.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/DomainUsers_thm.jpg new file mode 100644 index 0000000000..3895f33603 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/DomainUsers_thm.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/FileSharing.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/FileSharing.jpg new file mode 100644 index 0000000000..f96bb5549c Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/FileSharing.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/FileSharing_thm.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/FileSharing_thm.jpg new file mode 100644 index 0000000000..25c1c770bf Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/FileSharing_thm.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/InternetHost.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/InternetHost.jpg new file mode 100644 index 0000000000..27594ffed3 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/InternetHost.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/LoginPanel.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/LoginPanel.jpg new file mode 100644 index 0000000000..058dffd067 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/LoginPanel.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/LoginPanel_thm.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/LoginPanel_thm.jpg new file mode 100644 index 0000000000..80d8d0f9de Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/LoginPanel_thm.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/MyNetworkShares.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/MyNetworkShares.jpg new file mode 100644 index 0000000000..dab3765917 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/MyNetworkShares.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/MyNetworkShares_thm.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/MyNetworkShares_thm.jpg new file mode 100644 index 0000000000..7d8cb3cede Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/MyNetworkShares_thm.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/MyNetwork_thm.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/MyNetwork_thm.jpg new file mode 100644 index 0000000000..1ca69dc428 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/MyNetwork_thm.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/Security.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/Security.jpg new file mode 100644 index 0000000000..6690aa1f0a Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/Security.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/Security_thm.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/Security_thm.jpg new file mode 100644 index 0000000000..8ece96e6ab Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/Security_thm.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/ShareProperties.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/ShareProperties.jpg new file mode 100644 index 0000000000..59f0a6d276 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/ShareProperties.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/ShareProperties_thm.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/ShareProperties_thm.jpg new file mode 100644 index 0000000000..5066b68332 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/ShareProperties_thm.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/beserved_icon.gif b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/beserved_icon.gif new file mode 100644 index 0000000000..f1c2b42169 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/beserved_icon.gif differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/beserved_title.gif b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/beserved_title.gif new file mode 100644 index 0000000000..9f4e12d5d6 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/beserved_title.gif differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/mynetwork.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/mynetwork.jpg new file mode 100644 index 0000000000..72418a30f7 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/mynetwork.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/paypal_title.jpg b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/paypal_title.jpg new file mode 100644 index 0000000000..9545178f17 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/documentation/images/paypal_title.jpg differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/install.htm b/src/tests/add-ons/kernel/file_systems/beserved/documentation/install.htm new file mode 100644 index 0000000000..ddcd1133d4 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/documentation/install.htm @@ -0,0 +1,161 @@ + + + + + +BeServed Installation Instructions + + + + + + + + + + + + +


+ + + + + +
  + + + + +
 BeServed for BeOS Systems
+ + + + +
+

+ The BeOS verions of BeServed are provided in standard SoftwareValet-compatible + packages. Simply double-click on the downloaded file to perform the installation. + You may select whether you are installing the entire package, or client-only + utilities. Selecting client-only should be used when you want to browse files + on other computers, but not share any local files with others. +

+ + + + +
 BeServed for Linux
+ + + + +
+
+ The Linux file you will receive is called bs-linux-rh-i386.tar.gz. Once + downloaded, create a folder in which you wish to have BeServed installed, as in:
+
mkdir /usr/local/BeServed
+ Then, move the installation file into that folder and change the current working folder + to that location. +
mv bs-linux-rh-i386.tar.gz /usr/local/BeServed
+cd /usr/local/BeServed
+ Now, uncompress the installation files using the Linux tar command. Since the file you + download will be both archived and compress, you'll need to specify the -z and -x options, + or run gunzip before running tar.
+
tar -zxf bs-linux-rh-i386.tar.gz
+ Several files will be uncompressed. Run the install.sh file to perform the necessary + installation procedures.
+
./install.sh
+ BeServed should now be installed as a default daemon on your Linux system, it should + be running, and will be started each time the system is booted. You can now delete the + original file you downloaded.
+
rm -f bs-linux-rh-i386.tar.gz
+
+ + + + +
 BeServed for FreeBSD
+ + + + +
+
+ The FreeBSD file you will receive is called bs-freebsd-i386.tar.gz. Once + downloaded, create a folder in which you wish to have BeServed installed, as in:
+
mkdir /usr/local/BeServed
+ Then, move the installation file into that folder and change the current working folder + to that location. +
mv bs-freebsd-i386.tar.gz /usr/local/BeServed
+cd /usr/local/BeServed
+ Now, uncompress the installation files using the FreeBSD tar command. Since the file you + download will be both archived and compressed, you'll need to specify the -z and -x options, + or run gunzip before running tar.
+
tar -zxf bs-freebsd-i386.tar.gz
+ Several files will be uncompressed. Run the install.sh file to perform the necessary + installation procedures.
+
./install.sh
+ BeServed should now be installed as a default daemon on your FreeBSD system, it should + be running, and will be started each time the system is booted. You can now delete the + original file you downloaded.
+
rm -f bs-freebsd-i386.tar.gz
+
+ + + + +
 BeServed for Solaris
+ + + + +
+
+ The Solaris file you will receive is called bs-solaris-i386.tar.gz. Once + downloaded, create a folder in which you wish to have BeServed installed, as in:
+
mkdir /usr/local/BeServed
+ Then, move the installation file into that folder and change the current working folder + to that location. +
mv bs-solaris-i386.tar.gz /usr/local/BeServed
+cd /usr/local/BeServed
+ Now, uncompress the installation files using the gunzip command.
+
gunzip bs-solaris-i386.tar.gz
+ You should now have a file without the .gz extension, ending in .tar. You can use the + Solaris tar command to expand this archive. This is done using the -x tar option.
+
tar -xf bs-solaris-i386.tar
+ Several files will be uncompressed. Run the install.sh file to perform the necessary + installation procedures.
+
./install.sh
+ BeServed should now be installed as a default daemon on your Solaris system, it should + be running, and will be started each time the system is booted. You can now delete the + tar file that still remains.
+
rm -f bs-solaris-i386.tar
+ + + + +
 BeServed for Windows
+ + + + +
+
+ The compressed file you will receive is called bs-win32-nt-i386.zip. Once + downloaded, you will need to uncompress it into a temporary folder with WinZip or + another PKZIP-compatible extraction utility. From the temporary folder, simply run + setup.exe to perform the installation. The server can be started from the + Start menu. The File Sharing preferences application is also available from the + Start menu and allows you to specify the folders that will be shared with other + users without manually editing the settings file.

+ Once installed, you do not need to retain the original compressed file you downloaded. +
+
+
 
+ +

Copyright © 2001-2002 Teldar Corporation. + All rights reserved.
+ If you experience difficulties using this site, please contact webmaster@teldar.com.

+
+ + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/documentation/sharing.htm b/src/tests/add-ons/kernel/file_systems/beserved/documentation/sharing.htm new file mode 100644 index 0000000000..c1158e0f78 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/documentation/sharing.htm @@ -0,0 +1,178 @@ + + + + + +BeServed File Sharing Instructions + + + + + + + + + + + + +


+ + + + + + + + +
  + + + + +
 Using the Preferences Application
+ + + + +
+
+ BeOS and Windows systems support the BeServed File Sharing Preferences application + intended to make sharing folders on your computer easy and centralized in one + location. This graphical utility has the same capabilities as editing the + configuration file manually.

+ In BeOS, you will find the File Sharing preferences application by navigating through + your Be menu (the Deskbar) to the "Preferences" item, then locating and selecting + "File Sharing." On Windows systems, a program group should have been created in your + start menu for BeServed, which contains a shortcut to the preferences application. + Navigate through your start menu and select this shortcut.

+ The preferences application should look relatively similar on all supported systems. + BeOS screenshots are provided herein, but other versions of the interface are + virtually identical.

+

+ All the folders that are shared on this computer are listed in the main panel. + You can share an additional folder by clicking on the New button. You can + also edit the properties of an existing shared folder by highlighting it in the + list and clicking on the Edit button, or simply double-clicking on it. + If you have an existing shared folder that you no longer wish to share, highlight + it in the list and click on the Remove button.

+ When adding a new shared folder, or changing the properties of an existing one, + you will use the shared folder properties panel, shown below. This panel allows + you to select the folder you wish to share, to choose a friendly name by which + others will reference the folder, and to choose the security options that will + govern what users who access this folder will be permitted to do.

+

+ Basic access control is provided by the global setting "Users can make changes to + files and folders." When this option is enabled, users that access this shared + folder are able to add new files or sub-folders, modify the content of existing + files, delete files, and change BeOS attributes and indexes. You should only enable + this option if the files within your shared folder are not irreplaceable.

+ Beginning with version 1.2.0, you can optionally define different permission + levels for users and groups of users on your network. Users and groups are + defined and administered through the BeSure authentication server that comes + with BeServed. This is useful if you want some users to have permission to + change files, but not all users. It is also useful for requiring users to enter + passwords when your computer is connected to the Internet. You may not want any + BeServed user on the Internet to find and access your files. Securing your + public shared folder is the job of the authentication server.

+ To grant access to a specific user, you must have a BeSure authentication server + on your network, and you must have this computer configured to recognize its + authority to administer users. See the documentation on BeSure for more + information on setting up security for your BeServed-powered network.

+ The Domain User Access section of the share properties panel lists the + users and groups that have been granted specific permission levels for your + shared folder. To specify permission for an additional user or group, click on + the Add button. To remove the specific permissions granted to a user or + group, highlight the desired one in the list and click on the Remove button. + You cannot edit the permission granted to a specific user. If you wish to change + the permission level that user is granted, you need to remove the current entry + and add the user again, this time with the desired permission level. The Domain Users + panel shown below is displayed when assigning specific permission levels to a + user or group.

+

+ When you are finished editing the properties of your shared folder(s), click the Save + button to write your changes into the configuration file. Note that your changes + will not immediately take affect. There may be instances where you do not want to + interrupt services to users currently making use of file shares you may have edited + or completely removed. When you want to roll your changes out to users, click on + the Deploy button.

+
  + + + + +
 Using the Configuration File
+ + + + +
+
+ On systems that do not support the preferences application, you configure a computer to + share files by editing the BeServed-Settings script in the shared + configuration directory (/boot/home/config/settings).

+ This script can specify one or more folders you would like to make available + to other users on your network. Specifically, the "share" command accepts the + folder to be shared and a friendly alias for the folder. The command is written + as follows:

+
share directory as alias
+ If the directory or alias names contain spaces, you will need to enclose + them in quotation marks. Additionally, the command must reside on a single + line in the configuration file.

+ Examples:
+
share /boot/home as HomeDir
+share "/boot/home/My Projects" as "My Projects"

+ You may leave comments in the file by beginning the line with a # character. + For example:

+
# Share my home directory
+share /boot/home as HomeDir

+ If you need to enable security using the BeSure authentication server, you will + use the authenticate command and provide the host name or IP address of a computer + on your network that will run the BeSure server. This single computer will grant + or reject all login attempts to file shares on the network. The authenticate command + looks like this:

+
authenticate with 192.168.0.4

+ This command instructs the BeServed file server to consult the authentication server + to verify a user's credentials before granting access to file shares defined on that + server.

+ Once you have enabled security, you'll need to grant the specific permissions you + want each account to have. The currently available permissions are read and + write. These permissions are granted to users defined on the BeSure authentication + server using the grant command, as in:

+
grant read on "My Projects" to group everyone
+grant read,write on "My Projects" to johndoe

+ The first command grants read-only access to all users in the standard everyone + group (notice the group keyword). The second command grants read and write + access to the specific user johndoe.

+ The settings file must be saved as a plain text. Be cafeful when using editors + that provide formatting, such as StyledEdit or Gobe Productive, that you save + the file in plain text format. Otherwise, an editor will insert font, paragraph + and other formatting information into the file that BeServed will be unable to + interpret.

+ When you change the settings, you will need to stop and restart the server + application. The application is called beserved_server and resides in + the /boot/home/config/servers folder. You can force the server to review the + changed configuration by sending it the hangup, or HUP, signal in tradtional + Unix fashion. The signal is sent using the kill command, as in:

+
# kill -HUP process_id
+

+ where process_id is the process ID of the beserved server.

+ You can place this command in your startup sequence if you would like to have + file sharing automatically enabled upon system startup. Refer to your BeOS + documentation for information on editing startup scripts.

+ From the command prompt, you may type:

+
/boot/home/config/servers/beserved_server

+ Note: The ampersand (&) character is not needed at the end of the line, as in earlier + versions of the server. The server now runs as a proper Unix daemon, detaching + itself from the controlling terminal. Alternatively, you may open a Tracker + window for the /boot/home/config/servers folder and double-click on the beserved_server entry.

+
+
+
 
+ +

Copyright © 2001-2002 Teldar Corporation. + All rights reserved.
+ If you experience difficulties using this site, please contact webmaster@teldar.com.

+
+ + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/lshosts/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/lshosts/betalk.h new file mode 100644 index 0000000000..af38d0d926 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/lshosts/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +// The different types of network resources supported by BeServed. +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRITNER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 32768 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 128 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int nsid; + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +typedef struct rpcInfo +{ + thread_id rpcThread; + int32 quitXID; + + uint32 serverIP; + int32 serverPort; + int s; +} bt_rpcinfo; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket inPacket; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/lshosts/lshosts.c b/src/tests/add-ons/kernel/file_systems/beserved/lshosts/lshosts.c new file mode 100644 index 0000000000..942cca564b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/lshosts/lshosts.c @@ -0,0 +1,158 @@ +// LSHOSTS.C + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" + +// POSIX includes +#include "stdio.h" +#include "malloc.h" +#include "string.h" +#include "errno.h" +#include "socket.h" +#include "netdb.h" +#include "signal.h" + +#include "betalk.h" +#include "sysdepdefs.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +int main(int argc, char *argv[]); +static void recvAlarm(int signal); +static void usage(); + + +int main(int argc, char *argv[]) +{ + bt_request request; + struct sockaddr_in ourAddr, toAddr, fromAddr; + struct hostent *ent; + char buffer[8192]; + int sock, addrLen, bytes; + unsigned int serverIP; +#ifdef SO_BROADCAST + int on = 1; +#endif + + if (argc > 2) + usage(); + + memset(&toAddr, 0, sizeof(toAddr)); + toAddr.sin_family = AF_INET; + toAddr.sin_port = htons(BT_QUERYHOST_PORT); + if (argc == 1) + toAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); + else + { + ent = gethostbyname(argv[1]); + if (ent == NULL) + return 0; + + serverIP = ntohl(*((unsigned int *) ent->h_addr)); + toAddr.sin_addr.s_addr = htonl(serverIP); + } + + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock == INVALID_SOCKET) + return 0; + + memset(&ourAddr, 0, sizeof(ourAddr)); + ourAddr.sin_family = AF_INET; + ourAddr.sin_port = htons(BT_QUERYHOST_PORT); + ourAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(sock, (struct sockaddr *) &ourAddr, sizeof(ourAddr))) + if (errno != EADDRINUSE) + return 0; + + // Normally, a setsockopt() call is necessary to turn broadcast mode on + // explicitly, although some versions of Unix don't care. BeOS doesn't + // currently even define SO_BROADCAST, unless you have BONE installed. +#ifdef SO_BROADCAST + if (argc == 1) + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) + { + printf("Unable to obtain permission for a network broadcast.\n"); + closesocket(sock); + return 0; + } +#endif + signal(SIGALRM, recvAlarm); + + strcpy(request.signature, BT_RPC_SIGNATURE); + request.command = (argc == 1) ? BT_REQ_HOST_PROBE : BT_REQ_SHARE_PROBE; + if (sendto(sock, (char *) &request, sizeof(request), 0, (struct sockaddr *) &toAddr, sizeof(toAddr)) == -1) + { + printf("%s\n", strerror(errno)); + closesocket(sock); + return 0; + } + + memset(buffer, 0, sizeof(buffer)); + alarm(3); + + while (1) + { + addrLen = sizeof(fromAddr); + bytes = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *) &fromAddr, &addrLen); + if (bytes < 0) + { + if (errno == EINTR) + break; + } + + if (strncmp(buffer, BT_RPC_SIGNATURE, strlen(BT_RPC_SIGNATURE)) != 0) + if (argc == 1) + { + struct sockaddr_in *sin = (struct sockaddr_in *) &fromAddr; + ent = gethostbyaddr((char *) &sin->sin_addr, sizeof(sin->sin_addr), AF_INET); + if (ent) + printf("%s\n", ent->h_name); + else + { + uint8 *p = (uint8 *) &sin->sin_addr; + printf("%d.%d.%d.%d\n", p[0], p[1], p[2], p[3]); + } + } + else + { + bt_resource resource; + int bufPos = 0; + while (bufPos < bytes) + { + memcpy(&resource, buffer + bufPos, sizeof(bt_resource)); + resource.type = B_LENDIAN_TO_HOST_INT32(resource.type); + resource.subType = B_LENDIAN_TO_HOST_INT32(resource.subType); + if (resource.type == BT_SHARED_NULL) + break; + + bufPos += sizeof(bt_resource); + printf("%s (%s)\n", resource.name, + resource.type == BT_SHARED_FOLDER ? "Shared Files" : "Shared Printer"); + } + } + } + + alarm(0); + signal(SIGALRM, SIG_DFL); + closesocket(sock); +} + +static void recvAlarm(int signal) +{ + return; +} + +static void usage() +{ + printf("Usage: lshosts [host]\n"); + exit(0); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/lshosts/lshosts.proj b/src/tests/add-ons/kernel/file_systems/beserved/lshosts/lshosts.proj new file mode 100644 index 0000000000..f8f849c4fc Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/lshosts/lshosts.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/lshosts/lshosts_BONE.proj b/src/tests/add-ons/kernel/file_systems/beserved/lshosts/lshosts_BONE.proj new file mode 100644 index 0000000000..6c6c5baacc Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/lshosts/lshosts_BONE.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/lshosts/sysdepdefs.h b/src/tests/add-ons/kernel/file_systems/beserved/lshosts/sysdepdefs.h new file mode 100644 index 0000000000..6bb4bd5051 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/lshosts/sysdepdefs.h @@ -0,0 +1,10 @@ +#ifndef _SYSDEPDEFS_H_ +#define _SYSDEPDEFS_H_ + +#ifdef BONE_VERSION + +#define closesocket(s) close(s) + +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/BlowFish.h b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/BlowFish.h new file mode 100644 index 0000000000..cfc5667dd3 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/BlowFish.h @@ -0,0 +1,35 @@ +/* blowfish.h */ + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +#define UWORD32 unsigned long +#define UBYTE08 unsigned char + +#define MAXKEYBYTES 56 /* 448 bits */ + +typedef struct +{ + unsigned long S[4][256], P[18]; +} blf_ctx; + +unsigned long F(blf_ctx *, unsigned long x); +void Blowfish_encipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +void Blowfish_decipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +short InitializeBlowfish(blf_ctx *, unsigned char key[], int keybytes); + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE void blf_enc(blf_ctx *c, unsigned long *data, int blocks); +_IMPEXP_BESURE void blf_dec(blf_ctx *c, unsigned long *data, int blocks); +_IMPEXP_BESURE void blf_key(blf_ctx *c, unsigned char *key, int len); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/LoginPanel.cpp b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/LoginPanel.cpp new file mode 100644 index 0000000000..0ba35ba06d --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/LoginPanel.cpp @@ -0,0 +1,174 @@ +#include "Mime.h" +#include "TypeConstants.h" +#include "Application.h" +#include "InterfaceDefs.h" +#include "TranslationUtils.h" +#include "Button.h" +#include "Errors.h" +#include "Window.h" +#include "TextControl.h" +#include "Roster.h" +#include "Bitmap.h" +#include "Screen.h" +#include "OS.h" + +// POSIX includes +#include "errno.h" +#include "malloc.h" + +#include "LoginPanel.h" +#include "md5.h" + +// To create: +// BRect frame2(100, 150, 350, 290); +// LoginPanel *login = new LoginPanel(frame2); + + +// ----- LoginView ----------------------------------------------------- + +LoginView::LoginView(BRect rect, char *server, char *share) : + BView(rect, "LoginView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + strcpy(resource, share); + strcat(resource, " on "); + strcat(resource, server); + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.Teldar-FileSharing"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r(10, 72, 240, 92); + user = new BTextControl(r, "User", "User:", "", NULL); + user->SetDivider(55); + AddChild(user); + + r.top = 97; + r.bottom = r.top + 20; + password = new BTextControl(r, "Password", "Password:", "", NULL); + password->SetDivider(55); + password->TextView()->HideTyping(true); + AddChild(password); + + r.Set(LOGIN_PANEL_WIDTH - 160, LOGIN_PANEL_HEIGHT - 33, LOGIN_PANEL_WIDTH - 90, LOGIN_PANEL_HEIGHT - 13); + BButton *okBtn = new BButton(r, "OkayBtn", "Login", new BMessage(MSG_LOGIN_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(LOGIN_PANEL_WIDTH - 80, LOGIN_PANEL_HEIGHT - 33, LOGIN_PANEL_WIDTH - 10, LOGIN_PANEL_HEIGHT - 13); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_LOGIN_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); +} + +LoginView::~LoginView() +{ +} + +void LoginView::Draw(BRect rect) +{ + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + DrawString("Login Required"); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("The resource you've specified requires"); + MovePenTo(55, 40); + DrawString("permission to access it."); + + MovePenTo(13, 61); + DrawString("Resource:"); + MovePenTo(70, 61); + DrawString(resource); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); +} + + +// ----- LoginPanel ---------------------------------------------------------------------- + +LoginPanel::LoginPanel(BRect frame, char *server, char *share, bool show) : + BWindow(frame, "Login", B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) +{ + user[0] = password[0] = 0; + cancelled = false; + + BRect r = Bounds(); + loginView = new LoginView(r, server, share); + AddChild(loginView); + + if (show) + Show(); +} + +LoginPanel::~LoginPanel() +{ +} + +// Center() +// +void LoginPanel::Center() +{ + BScreen screen(this); + BRect screenFrame = screen.Frame(); + BRect winFrame; + winFrame.left = (screenFrame.Width() - 300) / 2; + winFrame.top = (screenFrame.Height() - 158) / 2; + winFrame.right = winFrame.left + 300; + winFrame.bottom = winFrame.top + 158; + MoveTo(winFrame.left, winFrame.top); + ResizeTo(300, 158); + + Show(); +} + +// MessageReceived() +// +void LoginPanel::MessageReceived(BMessage *msg) +{ + switch (msg->what) + { + case MSG_LOGIN_OK: + safeStringCopy(user, loginView->GetUser(), sizeof(user)); + safeStringCopy(password, loginView->GetPassword(), sizeof(password)); + md5EncodeString(password, md5passwd); + BWindow::Quit(); + break; + + case MSG_LOGIN_CANCEL: + cancelled = true; + BWindow::Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } +} + +void safeStringCopy(char *dest, const char *source, int destSize) +{ + int length = strlen(source); + if (length >= destSize) + length = destSize - 1; + + strncpy(dest, source, length); + dest[length] = 0; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/LoginPanel.h b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/LoginPanel.h new file mode 100644 index 0000000000..7b244fe654 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/LoginPanel.h @@ -0,0 +1,63 @@ +#include "Window.h" +#include "View.h" +#include "TextControl.h" +#include "Button.h" +#include "Bitmap.h" + +#include "betalk.h" + +const uint32 MSG_LOGIN_OK = 'LgOK'; +const uint32 MSG_LOGIN_CANCEL = 'LgCn'; + +#define LOGIN_PANEL_WIDTH 300 +#define LOGIN_PANEL_HEIGHT 158 + + +// ----- LoginView ----------------------------------------------------- + +class LoginView : public BView +{ + public: + LoginView(BRect rect, char *server, char *share); + ~LoginView(); + + void Draw(BRect rect); + + const char *GetUser() { return user->Text(); } + const char *GetPassword() { return password->Text(); } + + private: + BBitmap *icon; + BTextControl *user; + BTextControl *password; + char resource[256]; +}; + + +// ----- LoginPanel ---------------------------------------------------------------------- + +class LoginPanel : public BWindow +{ + public: + LoginPanel(BRect frame, char *server, char *share, bool show); + ~LoginPanel(); + + void Center(); + void MessageReceived(BMessage *msg); + bool IsCancelled() { return cancelled; } + + char user[MAX_NAME_LENGTH]; + char password[MAX_NAME_LENGTH]; + char md5passwd[MAX_NAME_LENGTH]; + + sem_id loginSem; + + private: + LoginView *loginView; + bool cancelled; +}; + + +// ----- Utilities ---------------------------------------------------------------------- + +void safeStringCopy(char *dest, const char *source, int destSize); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/betalk.h new file mode 100644 index 0000000000..af38d0d926 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +// The different types of network resources supported by BeServed. +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRITNER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 32768 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 128 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int nsid; + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +typedef struct rpcInfo +{ + thread_id rpcThread; + int32 quitXID; + + uint32 serverIP; + int32 serverPort; + int s; +} bt_rpcinfo; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket inPacket; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/ksocket_internal.h b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/ksocket_internal.h new file mode 100644 index 0000000000..e44e55c7b8 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/ksocket_internal.h @@ -0,0 +1,166 @@ +#ifndef _KSOCKET_INTERNAL_H + +#define _KSOCKET_INTERNAL_H + +#include + +struct ks_param_header +{ + port_id port; +}; + +struct ks_reply_header +{ + int error; +}; + +struct ks_socket_param +{ + struct ks_param_header header; + int family,type,proto; +}; + +struct ks_socket_reply +{ + struct ks_reply_header header; + int result; +}; + +struct ks_bind_param +{ + struct ks_param_header header; + int fd; + int size; + char addr[1]; +}; + +struct ks_bind_reply +{ + struct ks_reply_header header; + int result; +}; + +struct ks_getsockname_param +{ + struct ks_param_header header; + int fd; + int size; +}; + +struct ks_getsockname_reply +{ + struct ks_reply_header header; + int result; + int size; + char addr[1]; +}; + +struct ks_recvfrom_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; + int fromlen; +}; + +struct ks_recvfrom_reply +{ + struct ks_reply_header header; + ssize_t result; + int fromlen; + char data[1]; +}; + +struct ks_sendto_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; + int tolen; + char data[1]; +}; + +struct ks_sendto_reply +{ + struct ks_reply_header header; + ssize_t result; +}; + +struct ks_recv_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; +}; + +struct ks_recv_reply +{ + struct ks_reply_header header; + ssize_t result; + char data[1]; +}; + +struct ks_send_param +{ + struct ks_param_header header; + int fd; + size_t size; + int flags; + char data[1]; +}; + +struct ks_send_reply +{ + struct ks_reply_header header; + ssize_t result; +}; + +struct ks_listen_param +{ + struct ks_param_header header; + int fd,backlog; +}; + +struct ks_listen_reply +{ + struct ks_reply_header header; + int result; +}; + +struct ks_closesocket_param +{ + struct ks_param_header header; + int fd; +}; + +struct ks_closesocket_reply +{ + struct ks_reply_header header; + int result; +}; + +enum +{ + KS_SOCKET, + KS_BIND, + KS_GETSOCKNAME, + KS_GETPEERNAME, + KS_CONNECT, + KS_ACCEPT, + KS_RECVFROM, + KS_SENDTO, + KS_RECV, + KS_SEND, + KS_LISTEN, + KS_CLOSESOCKET, + KS_MESSAGE, + KS_QUIT +}; + +#define KSOCKET_DAEMON_NAME "ksocket_daemon" +#define KSOCKETD_SIGNATURE "application/x-vnd.BareCode-ksocketd" + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/makefile b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/makefile new file mode 100644 index 0000000000..0775937489 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/makefile @@ -0,0 +1,319 @@ +## BeOS Generic Makefile ## + +## Fill in the top section of this makefile to define exactly what sort of +## binary you are creating, and what sources, resources and libraries are +## needed to create it. The makefile will then determine the proper +## platform specific options. + +## Fill in the top section to define the binary being created and the makefile +## will make sure that all of the hard work is taken care of for you, for both +## PowerPC and Intel versions of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= mounthost + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= APP + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= mounthost.cpp LoginPanel.cpp rpc.cpp + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +#specify additional libraries to link against +# if libName.so or libName.a is the name of the library to link against +# then simply specify Name in the LIBS list +# if there is another naming scheme use the full binary +# name: my_library.so or my_lib.a +# libroot.so never needs to be specified here, although libbe.so does +LIBS= be net besure + + +# specify the paths to directories where additional +# libraries are to be found. /boot/develop/lib/PLATFORM/ is +# already set. The paths can be full or relative to this +# makefile. The paths included may not be recursive, so +# specify all of the needed paths explicitly +# Directories containing source-files are automatically added. +LIBPATHS= + +# specify additional directories where header files can be found +# directories where sources are found are included automatically +# included. +INCPATHS= + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= FULL + +# specify any symbols to be defined. The symbols will be +# set to a value of 1. For example specify DEBUG if you want +# DEBUG=1 to be set when compiling. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = + +# specify symbols +# if TRUE debug symbols will be created +SYMBOLS = + + +## Generic Makefile Rules --------------------------- +## DO NOT MODIFY BENEATH THIS LINE ----------------- + +# determine wheather running on x86 or ppc +MACHINE=$(shell uname -m) +ifeq ($(MACHINE), BePC) + CPU = x86 +else + CPU = ppc +endif + +# set the directory where object files and binaries will be created + OBJ_DIR := obj.$(CPU) + +# specify that the binary should be created in the object directory + TARGET := $(OBJ_DIR)/$(NAME) + +# specify the mimeset tool + MIMESET := mimeset + +# specify the tools for adding and removing resources + XRES = xres + +# SETTING: define debug symbols if desired +ifeq ($(SYMBOLS), TRUE) + CFLAGS += -g +endif + + +# platform specific settings + +# x86 Settings +ifeq ($(CPU), x86) +# set the compiler and compiler flags + CC = gcc + ##!! change next time : drivers get -no-fpic and -fpic goes away !! + CFLAGS += -fpic + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O1 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy + else + ifeq ($(WARNINGS), NONE) + + endif + endif + +# set the linker and linker flags + LD = gcc + LDFLAGS = + +# SETTING: set linker flags for each binary type + ifeq ($(TYPE), APP) + LDFLAGS += -Xlinker -soname=_APP_ + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -addon -Xlinker -soname=$(NAME) + else + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_ + endif + endif + endif + +else + +# ppc Settings +ifeq ($(CPU), ppc) +# set the compiler and compiler flags + CC = mwcc + CFLAGS += + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O7 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -w all + else + ifeq ($(WARNINGS), NONE) + CFLAGS += -w 0 + endif + endif + + # clear the standard environment variable + # now there are no standard libraries to link against + BELIBFILES= + +# set the linker and linker flags + LD = mwldppc + + ifeq ($(TYPE), APP) + LDFLAGS += + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -xms + endif + endif + + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nodefaults \ + -export all \ + -G \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/_KERNEL_ + else + # override the standard environment variable + LDFLAGS += -export pragma \ + -init _init_routine_ \ + -term _term_routine_ \ + -lroot \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/init_term_dyn.o \ + /boot/develop/lib/ppc/start_dyn.o + + endif + + +endif +endif + + +# psuedo-function for converting a list of source files in SRCS variable +# to a corresponding list of object files in $(OBJ_DIR)/xxx.o +# The "function" strips off the src file suffix (.ccp or .c or whatever) +# and then strips of the directory name, leaving just the root file name. +# It then appends the .o suffix and prepends the $(OBJ_DIR)/ path +define SRCS_LIST_TO_OBJS + $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ + $(basename $(notdir $(file)))))) +endef + +OBJS = $(SRCS_LIST_TO_OBJS) + +# create a unique list of paths to our sourcefiles +SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) + +# add source paths to VPATH if not already present +VPATH := +VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) + +# add source paths and include paths to INLCUDES if not already present +INCLUDES = $(foreach path, $(INCPATHS) $(SRC_PATHS), $(addprefix -I, $(path))) + + +# SETTING: add the -L prefix to all library paths to search +LINK_PATHS = $(foreach path, $(LIBPATHS) $(SRC_PATHS) , \ + $(addprefix -L, $(path))) + +# SETTING: add the -l prefix to all libs to be linked against +LINK_LIBS = $(foreach lib, $(LIBS), $(addprefix -l, $(lib))) + +# add to the linker flags +LDFLAGS += $(LINK_PATHS) $(LINK_LIBS) + +# SETTING: add the defines to the compiler flags +CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define))) + +# SETTING: use the archive tools if building a static library +# otherwise use the linker +ifeq ($(TYPE), STATIC) + BUILD_LINE = ar -cru $(NAME) $(OBJS) +else + BUILD_LINE = $(LD) -o $@ $(OBJS) $(LDFLAGS) +endif + +# create the resource instruction + ifeq ($(RSRCS), ) + DO_RSRCS := + else + DO_RSRCS := $(XRES) -o $(TARGET) $(RSRCS) + endif + + +# define the actual work to be done +default: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) $(RSRCS) + $(BUILD_LINE) + $(DO_RSRCS) + $(MIMESET) -f $@ + + +# rule to create the object file directory if needed +$(OBJ_DIR):: + @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 + +$(OBJ_DIR)/%.o : %.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cpp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.C + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CC + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CPP + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ + + +# empty rule. Things that depend on this rule will always get triggered +FORCE: + +# The generic clean command. Delete everything in the object folder. +clean :: FORCE + -rm -rf $(OBJ_DIR) + +# remove just the application from the object folder +rmapp :: + -rm -f $(TARGET) + +$(OBJ_DIR)/mounthost.o: mounthost.cpp ksocket_internal.h diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/makefile.bone b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/makefile.bone new file mode 100644 index 0000000000..07e6849743 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/makefile.bone @@ -0,0 +1,319 @@ +## BeOS Generic Makefile ## + +## Fill in the top section of this makefile to define exactly what sort of +## binary you are creating, and what sources, resources and libraries are +## needed to create it. The makefile will then determine the proper +## platform specific options. + +## Fill in the top section to define the binary being created and the makefile +## will make sure that all of the hard work is taken care of for you, for both +## PowerPC and Intel versions of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= mounthost + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= APP + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= mounthost.cpp LoginPanel.cpp rpc.cpp + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +#specify additional libraries to link against +# if libName.so or libName.a is the name of the library to link against +# then simply specify Name in the LIBS list +# if there is another naming scheme use the full binary +# name: my_library.so or my_lib.a +# libroot.so never needs to be specified here, although libbe.so does +LIBS= be bind socket besure + + +# specify the paths to directories where additional +# libraries are to be found. /boot/develop/lib/PLATFORM/ is +# already set. The paths can be full or relative to this +# makefile. The paths included may not be recursive, so +# specify all of the needed paths explicitly +# Directories containing source-files are automatically added. +LIBPATHS= + +# specify additional directories where header files can be found +# directories where sources are found are included automatically +# included. +INCPATHS=/boot/develop/headers/be/bone/sys + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= FULL + +# specify any symbols to be defined. The symbols will be +# set to a value of 1. For example specify DEBUG if you want +# DEBUG=1 to be set when compiling. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = + +# specify symbols +# if TRUE debug symbols will be created +SYMBOLS = + + +## Generic Makefile Rules --------------------------- +## DO NOT MODIFY BENEATH THIS LINE ----------------- + +# determine wheather running on x86 or ppc +MACHINE=$(shell uname -m) +ifeq ($(MACHINE), BePC) + CPU = x86 +else + CPU = ppc +endif + +# set the directory where object files and binaries will be created + OBJ_DIR := obj.$(CPU) + +# specify that the binary should be created in the object directory + TARGET := $(OBJ_DIR)/$(NAME) + +# specify the mimeset tool + MIMESET := mimeset + +# specify the tools for adding and removing resources + XRES = xres + +# SETTING: define debug symbols if desired +ifeq ($(SYMBOLS), TRUE) + CFLAGS += -g +endif + + +# platform specific settings + +# x86 Settings +ifeq ($(CPU), x86) +# set the compiler and compiler flags + CC = gcc + ##!! change next time : drivers get -no-fpic and -fpic goes away !! + CFLAGS += -fpic + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O1 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy + else + ifeq ($(WARNINGS), NONE) + + endif + endif + +# set the linker and linker flags + LD = gcc + LDFLAGS = + +# SETTING: set linker flags for each binary type + ifeq ($(TYPE), APP) + LDFLAGS += -Xlinker -soname=_APP_ + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -addon -Xlinker -soname=$(NAME) + else + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_ + endif + endif + endif + +else + +# ppc Settings +ifeq ($(CPU), ppc) +# set the compiler and compiler flags + CC = mwcc + CFLAGS += + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O7 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -w all + else + ifeq ($(WARNINGS), NONE) + CFLAGS += -w 0 + endif + endif + + # clear the standard environment variable + # now there are no standard libraries to link against + BELIBFILES= + +# set the linker and linker flags + LD = mwldppc + + ifeq ($(TYPE), APP) + LDFLAGS += + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -xms + endif + endif + + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nodefaults \ + -export all \ + -G \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/_KERNEL_ + else + # override the standard environment variable + LDFLAGS += -export pragma \ + -init _init_routine_ \ + -term _term_routine_ \ + -lroot \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/init_term_dyn.o \ + /boot/develop/lib/ppc/start_dyn.o + + endif + + +endif +endif + + +# psuedo-function for converting a list of source files in SRCS variable +# to a corresponding list of object files in $(OBJ_DIR)/xxx.o +# The "function" strips off the src file suffix (.ccp or .c or whatever) +# and then strips of the directory name, leaving just the root file name. +# It then appends the .o suffix and prepends the $(OBJ_DIR)/ path +define SRCS_LIST_TO_OBJS + $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ + $(basename $(notdir $(file)))))) +endef + +OBJS = $(SRCS_LIST_TO_OBJS) + +# create a unique list of paths to our sourcefiles +SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) + +# add source paths to VPATH if not already present +VPATH := +VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) + +# add source paths and include paths to INLCUDES if not already present +INCLUDES = $(foreach path, $(INCPATHS) $(SRC_PATHS), $(addprefix -I, $(path))) + + +# SETTING: add the -L prefix to all library paths to search +LINK_PATHS = $(foreach path, $(LIBPATHS) $(SRC_PATHS) , \ + $(addprefix -L, $(path))) + +# SETTING: add the -l prefix to all libs to be linked against +LINK_LIBS = $(foreach lib, $(LIBS), $(addprefix -l, $(lib))) + +# add to the linker flags +LDFLAGS += $(LINK_PATHS) $(LINK_LIBS) + +# SETTING: add the defines to the compiler flags +CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define))) + +# SETTING: use the archive tools if building a static library +# otherwise use the linker +ifeq ($(TYPE), STATIC) + BUILD_LINE = ar -cru $(NAME) $(OBJS) +else + BUILD_LINE = $(LD) -o $@ $(OBJS) $(LDFLAGS) +endif + +# create the resource instruction + ifeq ($(RSRCS), ) + DO_RSRCS := + else + DO_RSRCS := $(XRES) -o $(TARGET) $(RSRCS) + endif + + +# define the actual work to be done +default: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) $(RSRCS) + $(BUILD_LINE) + $(DO_RSRCS) + $(MIMESET) -f $@ + + +# rule to create the object file directory if needed +$(OBJ_DIR):: + @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 + +$(OBJ_DIR)/%.o : %.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cpp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.C + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CC + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CPP + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ + + +# empty rule. Things that depend on this rule will always get triggered +FORCE: + +# The generic clean command. Delete everything in the object folder. +clean :: FORCE + -rm -rf $(OBJ_DIR) + +# remove just the application from the object folder +rmapp :: + -rm -f $(TARGET) + +$(OBJ_DIR)/mounthost.o: mounthost.cpp ksocket_internal.h diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/makefile.net_server b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/makefile.net_server new file mode 100644 index 0000000000..0775937489 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/makefile.net_server @@ -0,0 +1,319 @@ +## BeOS Generic Makefile ## + +## Fill in the top section of this makefile to define exactly what sort of +## binary you are creating, and what sources, resources and libraries are +## needed to create it. The makefile will then determine the proper +## platform specific options. + +## Fill in the top section to define the binary being created and the makefile +## will make sure that all of the hard work is taken care of for you, for both +## PowerPC and Intel versions of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= mounthost + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= APP + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= mounthost.cpp LoginPanel.cpp rpc.cpp + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +#specify additional libraries to link against +# if libName.so or libName.a is the name of the library to link against +# then simply specify Name in the LIBS list +# if there is another naming scheme use the full binary +# name: my_library.so or my_lib.a +# libroot.so never needs to be specified here, although libbe.so does +LIBS= be net besure + + +# specify the paths to directories where additional +# libraries are to be found. /boot/develop/lib/PLATFORM/ is +# already set. The paths can be full or relative to this +# makefile. The paths included may not be recursive, so +# specify all of the needed paths explicitly +# Directories containing source-files are automatically added. +LIBPATHS= + +# specify additional directories where header files can be found +# directories where sources are found are included automatically +# included. +INCPATHS= + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= FULL + +# specify any symbols to be defined. The symbols will be +# set to a value of 1. For example specify DEBUG if you want +# DEBUG=1 to be set when compiling. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = + +# specify symbols +# if TRUE debug symbols will be created +SYMBOLS = + + +## Generic Makefile Rules --------------------------- +## DO NOT MODIFY BENEATH THIS LINE ----------------- + +# determine wheather running on x86 or ppc +MACHINE=$(shell uname -m) +ifeq ($(MACHINE), BePC) + CPU = x86 +else + CPU = ppc +endif + +# set the directory where object files and binaries will be created + OBJ_DIR := obj.$(CPU) + +# specify that the binary should be created in the object directory + TARGET := $(OBJ_DIR)/$(NAME) + +# specify the mimeset tool + MIMESET := mimeset + +# specify the tools for adding and removing resources + XRES = xres + +# SETTING: define debug symbols if desired +ifeq ($(SYMBOLS), TRUE) + CFLAGS += -g +endif + + +# platform specific settings + +# x86 Settings +ifeq ($(CPU), x86) +# set the compiler and compiler flags + CC = gcc + ##!! change next time : drivers get -no-fpic and -fpic goes away !! + CFLAGS += -fpic + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O1 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy + else + ifeq ($(WARNINGS), NONE) + + endif + endif + +# set the linker and linker flags + LD = gcc + LDFLAGS = + +# SETTING: set linker flags for each binary type + ifeq ($(TYPE), APP) + LDFLAGS += -Xlinker -soname=_APP_ + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -addon -Xlinker -soname=$(NAME) + else + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_ + endif + endif + endif + +else + +# ppc Settings +ifeq ($(CPU), ppc) +# set the compiler and compiler flags + CC = mwcc + CFLAGS += + +# SETTING: set the proper optimization level + ifeq ($(OPTIMIZE), FULL) + OPTIMIZER = -O7 + else + ifeq ($(OPTIMIZE), SOME) + OPTIMIZER = -O3 + else + ifeq ($(OPTIMIZE), NONE) + OPTIMIZER = + endif + endif + endif + + CFLAGS += $(OPTIMIZER) + +# SETTING: set warning level + ifeq ($(WARNINGS), ALL) + CFLAGS += -w all + else + ifeq ($(WARNINGS), NONE) + CFLAGS += -w 0 + endif + endif + + # clear the standard environment variable + # now there are no standard libraries to link against + BELIBFILES= + +# set the linker and linker flags + LD = mwldppc + + ifeq ($(TYPE), APP) + LDFLAGS += + else + ifeq ($(TYPE), SHARED) + LDFLAGS += -xms + endif + endif + + ifeq ($(TYPE), DRIVER) + LDFLAGS += -nodefaults \ + -export all \ + -G \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/_KERNEL_ + else + # override the standard environment variable + LDFLAGS += -export pragma \ + -init _init_routine_ \ + -term _term_routine_ \ + -lroot \ + /boot/develop/lib/ppc/glue-noinit.a \ + /boot/develop/lib/ppc/init_term_dyn.o \ + /boot/develop/lib/ppc/start_dyn.o + + endif + + +endif +endif + + +# psuedo-function for converting a list of source files in SRCS variable +# to a corresponding list of object files in $(OBJ_DIR)/xxx.o +# The "function" strips off the src file suffix (.ccp or .c or whatever) +# and then strips of the directory name, leaving just the root file name. +# It then appends the .o suffix and prepends the $(OBJ_DIR)/ path +define SRCS_LIST_TO_OBJS + $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ + $(basename $(notdir $(file)))))) +endef + +OBJS = $(SRCS_LIST_TO_OBJS) + +# create a unique list of paths to our sourcefiles +SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) + +# add source paths to VPATH if not already present +VPATH := +VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) + +# add source paths and include paths to INLCUDES if not already present +INCLUDES = $(foreach path, $(INCPATHS) $(SRC_PATHS), $(addprefix -I, $(path))) + + +# SETTING: add the -L prefix to all library paths to search +LINK_PATHS = $(foreach path, $(LIBPATHS) $(SRC_PATHS) , \ + $(addprefix -L, $(path))) + +# SETTING: add the -l prefix to all libs to be linked against +LINK_LIBS = $(foreach lib, $(LIBS), $(addprefix -l, $(lib))) + +# add to the linker flags +LDFLAGS += $(LINK_PATHS) $(LINK_LIBS) + +# SETTING: add the defines to the compiler flags +CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define))) + +# SETTING: use the archive tools if building a static library +# otherwise use the linker +ifeq ($(TYPE), STATIC) + BUILD_LINE = ar -cru $(NAME) $(OBJS) +else + BUILD_LINE = $(LD) -o $@ $(OBJS) $(LDFLAGS) +endif + +# create the resource instruction + ifeq ($(RSRCS), ) + DO_RSRCS := + else + DO_RSRCS := $(XRES) -o $(TARGET) $(RSRCS) + endif + + +# define the actual work to be done +default: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) $(RSRCS) + $(BUILD_LINE) + $(DO_RSRCS) + $(MIMESET) -f $@ + + +# rule to create the object file directory if needed +$(OBJ_DIR):: + @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 + +$(OBJ_DIR)/%.o : %.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cpp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.cp + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.C + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CC + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : %.CPP + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ + + +# empty rule. Things that depend on this rule will always get triggered +FORCE: + +# The generic clean command. Delete everything in the object folder. +clean :: FORCE + -rm -rf $(OBJ_DIR) + +# remove just the application from the object folder +rmapp :: + -rm -f $(TARGET) + +$(OBJ_DIR)/mounthost.o: mounthost.cpp ksocket_internal.h diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/md5.h b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/md5.h new file mode 100644 index 0000000000..4148570cd7 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/md5.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id: md5.h $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This code has some adaptations for the Ghostscript environment, but it + * will compile and run correctly in any environment with 8-bit chars and + * 32-bit ints. Specifically, it assumes that if the following are + * defined, they have the same meaning as in Ghostscript: P1, P2, P3, + * ARCH_IS_BIG_ENDIAN. + */ + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE void md5EncodeString(const char *source, char *dest); + +/* Initialize the algorithm. */ +#ifdef P1 +void md5_init(P1(md5_state_t *pms)); +#else +void md5_init(md5_state_t *pms); +#endif + +/* Append a string to the message. */ +#ifdef P3 +void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); +#else +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +#endif + +/* Finish the message and return the digest. */ +#ifdef P2 +void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); +#else +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/mounthost.cpp b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/mounthost.cpp new file mode 100644 index 0000000000..336227ad72 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/mounthost.cpp @@ -0,0 +1,234 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "socket.h" + +#include "betalk.h" +#include "rpc.h" +#include "md5.h" +#include "BlowFish.h" +#include "LoginPanel.h" + +#ifndef BONE_VERSION +#include "ksocket_internal.h" +#endif + +struct mount_nfs_params +{ + unsigned int serverIP; + char *server; + char *_export; + uid_t uid; + gid_t gid; + char *hostname; + char *folder; + char user[MAX_USERNAME_LENGTH + 1]; + char password[BT_AUTH_TOKEN_LENGTH * 2 + 1]; +}; + +int main (int argc, char *argv[]); +bool getAuthentication(unsigned int serverIP, char *shareName); +bool authenticateSelf(char *server, char *share, char *user, char *password, bool useTracker); +void getString(char *string, int length, bool displayChars); +void usage(); + + +int main(int argc, char *argv[]) +{ + mount_nfs_params params; + blf_ctx ctx; + hostent *ent; + struct stat st; + char hostname[256], server[256], share[256], folder[B_PATH_NAME_LENGTH], password[MAX_NAME_LENGTH + 1], *colon; + port_id port; + int length, hostArg = 1, pathArg = 2; + bool useTracker = false; + + BApplication theApp("application/x-vnd.teldar-mounthost"); + + if (argc < 3 || argc > 5) + { + usage(); + return 1; + + } + + if (*argv[1] == '-') + { + hostArg++; + pathArg++; + if (strcmp(argv[1], "-t") == 0) + useTracker = true; + else + printf("Option %s not understood and ignored\n", argv[1]); + } + + if (strcasecmp(argv[pathArg], "at") == 0) + pathArg++; + + if (stat(argv[pathArg], &st) != 0) + { + printf("The specified mount path does not exist.\n"); + return 1; + } + + strcpy(server, argv[hostArg]); + colon = strchr(server, ':'); + if (colon == NULL) + { + usage(); + return 1; + } + + *colon = 0; + strcpy(share, colon + 1); + strcpy(folder, argv[pathArg]); + + ent = gethostbyname(server); + if (ent == NULL) + { + printf("Server %s is unknown or its network address could not be\nresolved from that host name.\n", server); + return 1; + } + + unsigned int serverIP = ntohl(*((unsigned int *) ent->h_addr)); + +#ifndef BONE_VERSION + if (!be_roster->IsRunning(KSOCKETD_SIGNATURE)) + if (be_roster->Launch(KSOCKETD_SIGNATURE) < B_NO_ERROR) + { + printf("The kernel socket daemon ksocketd could not be started.\n"); + return 1; + } + + for (int32 i = 0; i < 10; i++) + { + port = find_port(KSOCKET_DAEMON_NAME); + + if (port < B_NO_ERROR) + snooze(1000000LL); + else + break; + } + + if (port < B_NO_ERROR) + { + printf ("The kernel socket daemon ksocketd is not responding.\n"); + return 1; + } +#endif + + int result = B_OK; + + params.user[0] = params.password[0] = 0; + + if (getAuthentication(serverIP, share)) + if (!authenticateSelf(server, share, params.user, password, useTracker)) + return 1; + else + { + // Copy the user name and password supplied in the authentication dialog. + sprintf(params.password, "%-*s%-*s", B_FILE_NAME_LENGTH, share, MAX_USERNAME_LENGTH, params.user); //crypt(password, "p1")); + params.password[BT_AUTH_TOKEN_LENGTH] = 0; + + blf_key(&ctx, (unsigned char *) password, strlen(password)); + blf_enc(&ctx, (unsigned long *) params.password, BT_AUTH_TOKEN_LENGTH / 4); + } + + params.serverIP = serverIP; + params.server = server; + params._export = share; + params.folder = folder; + params.uid = 0; + params.gid = 0; + + gethostname(hostname, 256); + params.hostname = hostname; + + result = mount("beserved_client", folder, NULL, 0, ¶ms, sizeof(params)); + + if (result < B_NO_ERROR) + { + printf ("Could not mount remote file share (%s).\n", strerror(errno)); + return 1; + } + + return 0; +} + +bool getAuthentication(unsigned int serverIP, char *shareName) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + int security; + + security = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_PREMOUNT, 1, strlen(shareName)); + btRPCPutArg(outPacket, B_STRING_TYPE, shareName, strlen(shareName)); + inPacket = btRPCSimpleCall(serverIP, BT_TCPIP_PORT, outPacket); + if (inPacket) + { + security = btRPCGetInt32(inPacket); + free(inPacket->buffer); + free(inPacket); + } + + return (security == BT_AUTH_BESURE); +} + +bool authenticateSelf(char *server, char *share, char *user, char *password, bool useTracker) +{ + char pwBuffer[50]; + + if (useTracker) + { + BRect frame(0, 0, LOGIN_PANEL_WIDTH, LOGIN_PANEL_HEIGHT); + LoginPanel *login = new LoginPanel(frame, server, share, false); + login->Center(); + status_t loginExit; + wait_for_thread(login->Thread(), &loginExit); + if (login->IsCancelled()) + return false; + + strcpy(user, login->user); + strcpy(password, login->md5passwd); + } + else + { + printf("Username: "); + getString(user, MAX_NAME_LENGTH, true); + printf("Password: "); + getString(pwBuffer, MAX_NAME_LENGTH, false); + md5EncodeString(pwBuffer, password); + } + + return true; +} + +void getString(char *string, int length, bool displayChars) +{ + char ch; + int pos = 0; + + while ((ch = getchar()) != '\n') + if (pos < length - 1) + string[pos++] = ch; + + string[pos] = 0; +} + +void usage() +{ + printf("Usage: mounthost [-bt] server:share [at] path\n"); + printf("Options:\n"); + printf("\t-t\tUse the BeOS Tracker to request the user name and password\n"); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/rpc.cpp b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/rpc.cpp new file mode 100644 index 0000000000..ba38ddaff2 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/rpc.cpp @@ -0,0 +1,471 @@ +#include "betalk.h" +#include "sysdepdefs.h" +#include "rpc.h" + +#include "signal.h" + + +int btRPCConnect(unsigned int serverIP, int port) +{ + struct sockaddr_in serverAddr; + int session; + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(port); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(serverIP); + + // Create a new socket to receive incoming requests. + session = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (session == INVALID_SOCKET) + return INVALID_SOCKET; + + // Bind that socket to the address constructed above. + if (connect(session, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return INVALID_SOCKET; + + return session; +} + +bool btRPCSend(int session, bt_outPacket *outPacket) +{ + // The XID will be 0. + btRPCPutInt32(outPacket, 0); + btRPCPutChar(outPacket, BT_CMD_TERMINATOR); + + if (btSendMsg(session, outPacket->buffer, outPacket->length, 0) == -1) + return false; + + return true; +} + +bool btRPCCheckSignature(int session) +{ + char signature[20]; + unsigned int sigLen; + + sigLen = strlen(BT_RPC_SIGNATURE); + memset(signature, 0, sigLen); + if (btRecvMsg(session, signature, sigLen, 0) == -1) + return false; + + // Check the signature's validity. + signature[sigLen] = 0; + return (strcmp(signature, BT_RPC_SIGNATURE) == 0); +} + +// btRPCSimpleCall() +// +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket) +{ + struct timeval timeout; + bt_inPacket *inPacket; + fd_set sockSet; + char *buffer; + int session; + int32 xid, length; + + // Establish a connection with the requested server, on the requested port. + // If we can't connect, abort and return a NULL packet. + inPacket = NULL; + session = btRPCConnect(serverIP, port); + if (session == INVALID_SOCKET) + return NULL; + + // If we connected, send the requested RPC packet. If the packet cannot be + // sent, the connection has dropped and we'll abort the call. + if (!btRPCSend(session, outPacket)) + { + closesocket(session); + return NULL; + } + + // Set a reasonable timeout period. Select() is used in leiu of alarm() because + // select() also aborts on error, alarm() effects all threads in a process. + FD_ZERO(&sockSet); + timeout.tv_sec = 8; + timeout.tv_usec = 0; + + // Block in select() waiting for activity. This will block until data is available + // or until a socket error is pending. + FD_SET(session, &sockSet); + select(session + 1, &sockSet, NULL, NULL, &timeout); + + // If our socket has data pending, then read the incoming RPC response packet. + // This should consist of a valid RPC signature, a tranaction ID (xid), the length + // of the variable data, and the data itself. + if (FD_ISSET(session, &sockSet)) + if (btRPCCheckSignature(session)) + { + if (btRecvMsg(session, &xid, sizeof(int32), 0) == -1 || + btRecvMsg(session, &length, sizeof(int32), 0) == -1) + goto abortCall; + + xid = B_LENDIAN_TO_HOST_INT32(xid); + length = B_LENDIAN_TO_HOST_INT32(length); + + // Now allocate a buffer of the appropriate length. If one cannot be + // allocated, we won't be able to store incoming information and the call + // must be aborted. + if (length > 0 && length < BT_RPC_MAX_PACKET_SIZE) + { + buffer = (char *) malloc(length + 1); + if (buffer) + { + // Read the remaining packet contents. The btRecv() function takes + // care of restarting the recv() when signal interrupts occur. It + // will always return -1 on error, even upon orderly shutdown of the peer. + if (btRecvMsg(session, buffer, length, 0) == -1) + { + free(buffer); + goto abortCall; + } + + // Terminate the buffer. + buffer[length] = 0; + + // Allocate a new incoming packet and set its buffer and length. + inPacket = (bt_inPacket *) malloc(sizeof(bt_inPacket)); + if (inPacket) + { + inPacket->buffer = buffer; + inPacket->length = length; + inPacket->offset = 0; + } + else + free(buffer); + } + } + } + + // Execution can naturally lead here or we can jump here from a failed attempt to + // send or receive an RPC packet. The socket is closed and the current incoming + // packet returned, which will be NULL upon failure. +abortCall: + shutdown(session, 2); + close(session); + return inPacket; +} + +int btRecvMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesRead = 0; + do + { + int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags); + if (bytes == -1) + return -1; + + bytesRead += bytes; + } while (bytesRead < dataLen); + + return bytesRead; +} + +// btRecv() +// +int btRecv(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = recv(sock, data, dataLen, flags); + if (bytes == 0) + return -1; + else if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +int btSendMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesSent = 0; + do + { + int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags); + if (bytes == -1) + return -1; + + bytesSent += bytes; + } while (bytesSent < dataLen); + + return bytesSent; +} + +// btSend() +// +int btSend(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = send(sock, data, dataLen, flags); + if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +void btDestroyInPacket(bt_inPacket *packet) +{ + if (packet) + { + if (packet->buffer) + free(packet->buffer); + + free(packet); + } +} + +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length) +{ + bt_outPacket *packet; + + packet = (bt_outPacket *) malloc(sizeof(bt_outPacket)); + if (!packet) + return NULL; + + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + { + free(packet); + return NULL; + } + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + +// btRPCPutChar(packet, BT_RPC_VERSION_HI); +// btRPCPutChar(packet, BT_RPC_VERSION_LO); + btRPCPutInt32(packet, 7 + (8 * argc) + length); + btRPCPutChar(packet, command); + btRPCPutChar(packet, argc); + + return packet; +} + +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length) +{ + btRPCPutInt32(packet, type); + btRPCPutInt32(packet, length); + btRPCPutBinary(packet, data, length); +} + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error, int length) +{ + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + return; + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + btRPCPutInt32(packet, xid); + btRPCPutInt32(packet, 0); + btRPCPutInt32(packet, error); +} + +void btRPCSendAck(int client, bt_outPacket *packet) +{ + if (packet) + if (packet->buffer) + { + *(int32 *)(&packet->buffer[9]) = B_HOST_TO_LENDIAN_INT32(packet->length - 13); + btSendMsg(client, packet->buffer, packet->length, 0); + free(packet->buffer); + } +} + +unsigned char btRPCGetChar(bt_inPacket *packet) +{ + unsigned char value; + + if (packet->offset < packet->length) + value = (unsigned char) packet->buffer[packet->offset]; + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + if (bytes > 0) + memcpy(str, &packet->buffer[packet->offset], bytes); + + str[bytes] = 0; + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return ERANGE; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return ERANGE; + + if (length < bytes) + return ERANGE; + + if (bytes > 0) + memcpy(buffer, &packet->buffer[packet->offset], bytes); + + packet->offset += bytes; + return bytes; +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +int btRPCGetStat(bt_inPacket *packet, struct stat *st) +{ + st->st_dev = 0; + st->st_nlink = btRPCGetInt32(packet); + st->st_uid = btRPCGetInt32(packet); + st->st_gid = btRPCGetInt32(packet); + st->st_size = btRPCGetInt64(packet); + st->st_blksize = btRPCGetInt32(packet); + st->st_rdev = btRPCGetInt32(packet); + st->st_ino = btRPCGetInt64(packet); + st->st_mode = btRPCGetInt32(packet); + st->st_atime = btRPCGetInt32(packet); + st->st_mtime = btRPCGetInt32(packet); + st->st_ctime = btRPCGetInt32(packet); +} + +void btRPCPutStat(bt_outPacket *packet, struct stat *st) +{ + if (packet && st) + { + btRPCPutInt32(packet, (int) st->st_nlink); + btRPCPutInt32(packet, (int) st->st_uid); + btRPCPutInt32(packet, (int) st->st_gid); + btRPCPutInt64(packet, (int64) st->st_size); + btRPCPutInt32(packet, (int) st->st_blksize); + btRPCPutInt32(packet, (int) st->st_rdev); + btRPCPutInt64(packet, (int64) st->st_ino); + btRPCPutInt32(packet, (int) st->st_mode); + btRPCPutInt32(packet, (int) st->st_atime); + btRPCPutInt32(packet, (int) st->st_mtime); + btRPCPutInt32(packet, (int) st->st_ctime); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/rpc.h b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/rpc.h new file mode 100644 index 0000000000..89c1194d2b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/rpc.h @@ -0,0 +1,25 @@ +// rpc.h + +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket); +int btRPCConnect(unsigned int serverIP, int port); +bool btRPCSend(int session, bt_outPacket *outPacket); +bool btRPCCheckSignature(int session); +void btDestroyInPacket(bt_inPacket *packet); +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error, int length); +void btRPCSendAck(int client, bt_outPacket *packet); +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char *btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +void btRPCGrowPacket(bt_outPacket *packet, int bytes); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/mounthost/sysdepdefs.h b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/sysdepdefs.h new file mode 100644 index 0000000000..6bb4bd5051 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/mounthost/sysdepdefs.h @@ -0,0 +1,10 @@ +#ifndef _SYSDEPDEFS_H_ +#define _SYSDEPDEFS_H_ + +#ifdef BONE_VERSION + +#define closesocket(s) close(s) + +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/RPCPendingCalls.h b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/RPCPendingCalls.h new file mode 100644 index 0000000000..30693a699e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/RPCPendingCalls.h @@ -0,0 +1,51 @@ +#ifndef _RPCPENDINGCALLS_H + +#define _RPCPENDINGCALLS_H + +#include +#include +#include + +struct SemaphorePool +{ + sem_id *fPool; + int32 fPoolCount; + int32 fPoolSize; + sem_id fPoolSem; +}; + +void SemaphorePoolInit (struct SemaphorePool *pool); +void SemaphorePoolDestroy (struct SemaphorePool *pool); +sem_id SemaphorePoolGet(struct SemaphorePool *pool); +void SemaphorePoolPut (struct SemaphorePool *pool, sem_id sem); + +struct PendingCall +{ + struct PendingCall *next; + + sem_id sem; + struct sockaddr_in addr; + int32 xid; + uint8 *buffer; +}; + +void PendingCallInit (struct PendingCall *call); +void PendingCallDestroy (struct PendingCall *call); + +struct RPCPendingCalls +{ + struct PendingCall *fFirst; + sem_id fSem; + struct SemaphorePool fPool; +}; + +void RPCPendingCallsInit (struct RPCPendingCalls *calls); +void RPCPendingCallsDestroy (struct RPCPendingCalls *calls); + +struct PendingCall *RPCPendingCallsAddPendingCall (struct RPCPendingCalls *calls, + int32 xid, const struct sockaddr_in *addr); + +struct PendingCall *RPCPendingCallsFindAndRemovePendingCall (struct RPCPendingCalls *calls, + int32 xid, const struct sockaddr_in *addr); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/Resource.rsrc b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/Resource.rsrc new file mode 100644 index 0000000000..5d27b287df Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/Resource.rsrc differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/Server.proj b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/Server.proj new file mode 100644 index 0000000000..878619c8fd Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/Server.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/Server_BONE.proj b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/Server_BONE.proj new file mode 100644 index 0000000000..1525835975 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/Server_BONE.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/authentication.c b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/authentication.c new file mode 100644 index 0000000000..02b5577f88 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/authentication.c @@ -0,0 +1,265 @@ +#include "betalk.h" +#include "authentication.h" +#include "sysdepdefs.h" +#include "netdb.h" + +#include "ctype.h" +#include "signal.h" +#include "stdlib.h" + +extern bool getAuthServerAddress(const char *name); + +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket); +int btRPCConnect(unsigned int serverIP, int port); +bool btRPCSend(int session, bt_outPacket *outPacket); +bool btRPCCheckSignature(int session); +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); + + +int btRPCConnect(unsigned int serverIP, int port) +{ + struct sockaddr_in serverAddr; + int session; + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(port); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(serverIP); + + // Create a new socket to receive incoming requests. + session = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (session == INVALID_SOCKET) + return INVALID_SOCKET; + + // Bind that socket to the address constructed above. + if (connect(session, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return INVALID_SOCKET; + + return session; +} + +bool btRPCSend(int session, bt_outPacket *outPacket) +{ + // The XID will be 0. + btRPCPutInt32(outPacket, 0); + btRPCPutChar(outPacket, BT_CMD_TERMINATOR); + + if (btSendMsg(session, outPacket->buffer, outPacket->length, 0) == -1) + return false; + + return true; +} + +bool btRPCCheckSignature(int session) +{ + char signature[20]; + unsigned int sigLen; + + sigLen = strlen(BT_RPC_SIGNATURE); + memset(signature, 0, sigLen); + if (btRecvMsg(session, signature, sigLen, 0) == -1) + return false; + + // Check the signature's validity. + signature[sigLen] = 0; + return (strcmp(signature, BT_RPC_SIGNATURE) == 0); +} + +// btRPCSimpleCall() +// +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket) +{ + struct timeval timeout; + bt_inPacket *inPacket; + fd_set sockSet; + char *buffer; + int session; + int32 xid, length; + + // Establish a connection with the requested server, on the requested port. + // If we can't connect, abort and return a NULL packet. + inPacket = NULL; + session = btRPCConnect(serverIP, port); + if (session == INVALID_SOCKET) + return NULL; + + // If we connected, send the requested RPC packet. If the packet cannot be + // sent, the connection has dropped and we'll abort the call. + if (!btRPCSend(session, outPacket)) + { + closesocket(session); + return NULL; + } + + // Set a reasonable timeout period. Select() is used in leiu of alarm() because + // select() also aborts on error, alarm() effects all threads in a process. + FD_ZERO(&sockSet); + timeout.tv_sec = 8; + timeout.tv_usec = 0; + + // Block in select() waiting for activity. This will block until data is available + // or until a socket error is pending. + FD_SET(session, &sockSet); + select(session + 1, &sockSet, NULL, NULL, &timeout); + + // If our socket has data pending, then read the incoming RPC response packet. + // This should consist of a valid RPC signature, a tranaction ID (xid), the length + // of the variable data, and the data itself. + if (FD_ISSET(session, &sockSet)) + if (btRPCCheckSignature(session)) + { + if (btRecvMsg(session, &xid, sizeof(int32), 0) == -1 || + btRecvMsg(session, &length, sizeof(int32), 0) == -1) + goto abortCall; + + // Now allocate a buffer of the appropriate length. If one cannot be + // allocated, we won't be able to store incoming information and the call + // must be aborted. + xid = B_LENDIAN_TO_HOST_INT32(xid); + length = B_LENDIAN_TO_HOST_INT32(length); + if (length > 0 && length < BT_RPC_MAX_PACKET_SIZE) + { + buffer = (char *) malloc(length + 1); + if (buffer) + { + // Read the remaining packet contents. The btRecvMsg() function takes + // care of restarting the recv() when signal interrupts occur. It + // will always return -1 on error, even upon orderly shutdown of the peer. + if (btRecvMsg(session, buffer, length, 0) == -1) + { + free(buffer); + goto abortCall; + } + + // Terminate the buffer. + buffer[length] = 0; + + // Allocate a new incoming packet and set its buffer and length. + inPacket = (bt_inPacket *) malloc(sizeof(bt_inPacket)); + if (inPacket) + { + inPacket->buffer = buffer; + inPacket->length = length; + inPacket->offset = 0; + } + else + free(buffer); + } + } + } + + // Execution can naturally lead here or we can jump here from a failed attempt to + // send or receive an RPC packet. The socket is closed and the current incoming + // packet returned, which will be NULL upon failure. +abortCall: + shutdown(session, 2); + close(session); + return inPacket; +} + +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length) +{ + bt_outPacket *packet; + + packet = (bt_outPacket *) malloc(sizeof(bt_outPacket)); + if (!packet) + return NULL; + + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + { + free(packet); + return NULL; + } + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + +// btRPCPutChar(packet, BT_RPC_VERSION_HI); +// btRPCPutChar(packet, BT_RPC_VERSION_LO); + btRPCPutInt32(packet, 7 + (8 * argc) + length); + btRPCPutChar(packet, command); + btRPCPutChar(packet, argc); + + return packet; +} + +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length) +{ + btRPCPutInt32(packet, type); + btRPCPutInt32(packet, length); + btRPCPutBinary(packet, data, length); +} + +bool authenticateUser(char *user, char *password) +{ + extern char *authServerName; + extern unsigned int authServerIP; + bt_outPacket *outPacket; + bt_inPacket *inPacket; + bool authenticated = false; + int error; + + getAuthServerAddress(authServerName); + + outPacket = btRPCPutHeader(BT_CMD_AUTH, 2, strlen(user) + BT_AUTH_TOKEN_LENGTH); + if (outPacket) + { + btRPCPutArg(outPacket, B_STRING_TYPE, user, strlen(user)); + btRPCPutArg(outPacket, B_STRING_TYPE, password, BT_AUTH_TOKEN_LENGTH); + inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket); + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + authenticated = true; + + free(inPacket->buffer); + free(inPacket); + } + + free(outPacket->buffer); + free(outPacket); + } + + return authenticated; +} + +void getUserGroups(char *user, char **groups) +{ + extern char *authServerName; + extern unsigned int authServerIP; + bt_outPacket *outPacket; + bt_inPacket *inPacket; + int i, error; + + getAuthServerAddress(authServerName); + + outPacket = btRPCPutHeader(BT_CMD_WHICHGROUPS, 1, strlen(user)); + if (outPacket) + { + btRPCPutArg(outPacket, B_STRING_TYPE, user, strlen(user)); + inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket); + if (inPacket) + { + i = 0; + error = btRPCGetInt32(inPacket); + while (error == B_OK) + { + groups[i++] = btRPCGetNewString(inPacket); + error = btRPCGetInt32(inPacket); + } + + free(inPacket->buffer); + free(inPacket); + } + + free(outPacket->buffer); + free(outPacket); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/authentication.h b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/authentication.h new file mode 100644 index 0000000000..8c784ff771 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/authentication.h @@ -0,0 +1,2 @@ +bool authenticateUser(char *user, char *password); +void getUserGroups(char *user, char **groups); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/beserved_server.c b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/beserved_server.c new file mode 100644 index 0000000000..22068c4b12 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/beserved_server.c @@ -0,0 +1,1485 @@ +// btAdd.cpp : Defines the entry point for the console application. +// + +// To-do: +// +// X Better reconnect logic +// _ Node monitoring +// _ Don't allow following links outside the shared folder +// _ Restart of server erases inode-to-filename map +// _ Ability to reconnect shares at login +// _ Restricting logon times via a schedule +// _ Distributed file sharing +// + +// dividing the files: +// 1. main(), start/stop service, request thread launching, misc +// 2. signal handlers +// 3. UDP command thread/handlers +// 4. config file parsing +// 5. RPC code +// 6. actual file handling commands +// 7. net file handling commands + +// Potential Uses: +// 1. Domain server, keeping track of users for logging in +// 2. File server, to share BeOS volume files across a network +// 3. Document management, to store documents with attributes +// 4. Version Control System, to manage multiple versions of documents +// 5. General directory server, for local or network settings and information + +#include "FindDirectory.h" + +#include "betalk.h" +#include "sessions.h" +#include "rpc_handlers.h" +#include "rpc_workers.h" +#include "file_shares.h" +#include "readerWriter.h" + +#include "sysdepdefs.h" +#include "fsproto.h" +#include "netdb.h" + +#include "ctype.h" +#include "time.h" +#include "signal.h" +#include "stdlib.h" +#include "syslog.h" +#include "sys/utsname.h" + +#define BT_MAX_THREADS 100 +#define BT_MAX_RETRIES 3 + +#define BT_MAIN_NAME "BeServed Daemon" +#define BT_THREAD_NAME "BeServed Handler" +#define BT_HOST_THREAD_NAME "BeServed Host Publisher" +#define BT_SIGNATURE "application/x-vnd.Teldar-BeServed" + +#define PATH_ROOT "/boot" +#define PATH_DELIMITER '/' + +#ifndef iswhite +#define iswhite(c) ((c == ' ' || c == '\t')) +#endif + + +int main(int argc, char *argv[]); +void daemonInit(); +bool dateCheck(); +int32 btSendHost(void *data); +int getSharedResources(char *buffer, int bufSize); +void getHostInfo(bt_hostinfo *info); +int getHostUsers(char *buffer); +void startService(); +void endService(int sig); +void restartService(); +void initShares(); +void freeFileHandles(); +void freeFileShares(); +void getFileShare(const char *buffer); +void getShareProperty(const char *buffer); +void getGrant(const char *buffer); +void getAuthenticate(const char *buffer); +bool getAuthServerAddress(const char *name); +void addUserRights(char *share, char *user, int rights, bool isGroup); +int getToken(); +int receiveRequest(bt_session_t *session); +void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]); +void launchThread(int client, struct sockaddr_in *addr); +int tooManyConnections(unsigned int s_addr); +void sendErrorToClient(int client, unsigned int xid, int error); +void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command); +int32 requestThread(void *data); + + +bt_node *rootNode = NULL; +bt_session_t *rootSession = NULL; +bt_fileShare_t fileShares[BT_MAX_FILE_SHARES]; +char tokBuffer[B_PATH_NAME_LENGTH], *tokPtr; +bool running = true; +int server; +char authServerName[B_FILE_NAME_LENGTH]; +unsigned int authServerIP; +thread_id hostThread; +bt_managed_data sessionData; +bt_managed_data handleData; + +bt_command_t dirCommands[] = +{ + { BT_CMD_PREMOUNT, netbtPreMount, true, 1, { B_STRING_TYPE } }, + { BT_CMD_MOUNT, netbtMount, true, 3, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_FSINFO, netbtFSInfo, true, 1, { B_INT64_TYPE } }, + { BT_CMD_LOOKUP, netbtLookup, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_STAT, netbtStat, true, 1, { B_INT64_TYPE } }, + { BT_CMD_READDIR, netbtReadDir, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_READ, netbtRead, true, 3, { B_INT64_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_WRITE, netbtWrite, true, 5, { B_INT64_TYPE, B_INT64_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_STRING_TYPE } }, + { BT_CMD_CREATE, netbtCreate, true, 4, { B_INT64_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_TRUNCATE, netbtTruncate, true, 2, { B_INT64_TYPE, B_INT64_TYPE } }, + { BT_CMD_MKDIR, netbtCreateDir, true, 3, { B_INT64_TYPE, B_STRING_TYPE, B_INT32_TYPE } }, + { BT_CMD_RMDIR, netbtDeleteDir, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_RENAME, netbtRename, true, 4, { B_INT64_TYPE, B_STRING_TYPE, B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_UNLINK, netbtUnlink, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_READLINK, netbtReadLink, true, 1, { B_INT64_TYPE } }, + { BT_CMD_SYMLINK, netbtSymLink, true, 3, { B_INT64_TYPE, B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_WSTAT, netbtWStat, true, 8, { B_INT64_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_READATTRIB, netbtReadAttrib, true, 5, { B_INT64_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_WRITEATTRIB, netbtWriteAttrib, true, 6, { B_INT64_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_READATTRIBDIR, netbtReadAttribDir, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_REMOVEATTRIB, netbtRemoveAttrib, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_STATATTRIB, netbtStatAttrib, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_READINDEXDIR, netbtReadIndexDir, true, 1, { B_STRING_TYPE } }, + { BT_CMD_CREATEINDEX, netbtCreateIndex, true, 3, { B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_REMOVEINDEX, netbtRemoveIndex, true, 1, { B_STRING_TYPE } }, + { BT_CMD_STATINDEX, netbtStatIndex, true, 1, { B_STRING_TYPE } }, + { BT_CMD_READQUERY, netbtReadQuery, true, 2, { B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_COMMIT, netbtCommit, true, 1, { B_INT64_TYPE } }, + { BT_CMD_PRINTJOB_NEW, netbtPrintJobNew, false, 0, { 0 } }, + { BT_CMD_PRINTJOB_DATA, netbtPrintJobData, false, 0, { 0 } }, + { BT_CMD_PRINTJOB_COMMIT, netbtPrintJobCommit, false, 0, { 0 } }, + { BT_CMD_AUTHENTICATE, netbtAuthenticate, false, 0, { 0 } }, + { BT_CMD_QUIT, netbtQuit, true, 0, { 0 } }, + { 0, NULL, false, 0, { 0 } } +}; + +char *keywords[] = +{ + "share", + "as", + "set", + "read", + "write", + "read-write", + "promiscuous", + "on", + "to", + "authenticate", + "with", + "group", + "printer", + "print", + "is", + "spooled", + "device", + "type", + NULL +}; + +/*---------------------------------------------------------------- +class BeServedServer : public BApplication +{ + thread_id appThread; + bool running; + + public: + BeServedServer(const char *signature); + + virtual void ReadyToRun(); + virtual bool QuitRequested(); +}; + +BeServedServer::BeServedServer(const char *signature) + : BApplication(signature) +{ +} + +void BeServedServer::ReadyToRun() +{ + running = true; + appThread = spawn_thread(appMain, BT_MAIN_NAME, B_NORMAL_PRIORITY, this); + resume_thread(appThread); +} + +bool BeServedServer::QuitRequested() +{ + status_t result; + + if (!BApplication::QuitRequested()) + return false; + + running = false; + wait_for_thread(appThread, &result); + return true; +} + +int main(int argc, char *argv[]) +{ + BeServedServer app(BT_SIGNATURE); + app.Run(); + return 0; +} +----------------------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + daemonInit(); + + initShares(); + signal(SIGINT, endService); + signal(SIGTERM, endService); + signal(SIGHUP, restartService); + signal(SIGPIPE, SIG_IGN); + + if (initManagedData(&handleData)) + { + if (initManagedData(&sessionData)) + { + hostThread = spawn_thread(btSendHost, BT_HOST_THREAD_NAME, B_NORMAL_PRIORITY, 0); + resume_thread(hostThread); + + // Run the daemon. We will not return until the service is being stopped. + startService(); + + if (hostThread > 0) + kill_thread(hostThread); + + closeManagedData(&sessionData); + } + + closeManagedData(&handleData); + } + + return 0; +} + +bool dateCheck() +{ + struct stat st; + time_t curTime; + + time(&curTime); + if (curTime > 1012537700) + return false; + + if (stat("/boot/home/config/servers/beserved_server", &st) == 0) + if (curTime < st.st_ctime || curTime > st.st_ctime + 7776000) + return false; + + return true; +} + +void daemonInit() +{ + int i; + + // Cause the parent task to terminate, freeing the terminal. + if (fork() != 0) + exit(0); + + // In the child process, become the session leader. + setsid(); + + // Now fork again, causing the first child to exit, since the session + // leader can be assigned a controlling terminal under SVR4. + signal(SIGHUP, SIG_IGN); + if (fork() != 0) + exit(0); + + // Change to the root directory, since if we hold on to a working + // folder that was in a mounted file system, that file system cannot + // be unmounted. + chdir("/"); + + // Reset the file creation mask to zero to eliminate the inherited value. + umask(0); + + // Close open file descriptors. Since we can't know how many of a + // potentially unlimited value can be open, just close the first 64 + // and assume that will be enough. + for (i = 0; i < 64; i++) + close(i); + + // Open the syslog. + openlog("beserved_server", LOG_PID, LOG_DAEMON); +} + +void restartService() +{ + bt_fileShare_t *oldShares; + int i; + + // Delay all mounting and other file system operations. + beginWriting(&handleData); + beginWriting(&sessionData); + + // Copy existing share data. + oldShares = (bt_fileShare_t *) malloc(sizeof(bt_fileShare_t) * BT_MAX_FILE_SHARES); + if (oldShares) + { + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + memcpy(&oldShares[i], &fileShares[i], sizeof(bt_fileShare_t)); + + // Reload the share data. + initShares(); + + // Now loop through the old file shares. For each one, check if the same + // path exists in the new shares. + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (oldShares[i].used) + { + bt_session_t *s; + int share = btGetShareIdByPath(oldShares[i].path); + if (share == -1) + { + for (s = rootSession; s; s = s->next) + if (s->share == i) + s->killed = true; + } + else if (share != i) + { + for (s = rootSession; s; s = s->next) + if (s->share == i) + s->share = share; + } + } + + free(oldShares); + } + + // Resume normal operation. + endWriting(&sessionData); + endWriting(&handleData); +} + +int32 btSendHost(void *data) +{ + bt_request request; + bt_hostinfo info; + struct sockaddr_in serverAddr, clientAddr; + char buffer[4096]; + int server, addrLen, bufLen, replyLen; + + buffer[0] = 0; + bufLen = sizeof(buffer); + + server = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (server == INVALID_SOCKET) + return -1; + + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(BT_QUERYHOST_PORT); + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Bind that socket to the address constructed above. + if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return -1; + + while (running) + { + addrLen = sizeof(struct sockaddr_in); + replyLen = 0; + if (recvfrom(server, (char *) &request, sizeof(request), 0, (struct sockaddr *) &clientAddr, &addrLen) <= 0) + continue; + + switch (request.command) + { + case BT_REQ_HOST_PROBE: + gethostname(buffer, bufLen); + break; + + case BT_REQ_SHARE_PROBE: + replyLen = getSharedResources(buffer, sizeof(buffer)); + break; + + case BT_REQ_HOST_INFO: + getHostInfo(&info); + memcpy(buffer, &info, sizeof(bt_hostinfo)); + replyLen = sizeof(bt_hostinfo); + break; + + case BT_REQ_HOST_USERS: + replyLen = getHostUsers(buffer); + break; + + case BT_REQ_AUTH_TYPES: + break; + } + + // If no reply length has been specified, calculate it now by taking the + // length of the buffer. + if (replyLen == 0) + replyLen = strlen(buffer); + + sendto(server, buffer, replyLen, 0, (struct sockaddr *) &clientAddr, addrLen); + } + + // Close the socket. Technically, I believe we should call shutdown() + // first, but the BeOS header file socket.h indicates that this + // function is not currently working. It is present but may not have + // any effect. + shutdown(server, 2); + closesocket(server); + return 0; +} + +// getSharedResources() +// +int getSharedResources(char *buffer, int bufSize) +{ + bt_resource resource; + int i, bufPos = 0; + + // If the supplied buffer can't hold at least two resource structures, one + // for a shared resource and one to terminate the list, then don't bother + // building the list. + if (bufSize < 2 * sizeof(bt_resource)) + return 0; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + { + // If this is the last resource structure that will fit in the + // buffer, then don't add any more into the list. + if (bufPos + sizeof(bt_resource) >= bufSize) + break; + + // Fill out the resource structure. + resource.type = B_HOST_TO_LENDIAN_INT32(BT_SHARED_FOLDER); + strcpy(resource.name, fileShares[i].name); + + // Copy the resource structure into the buffer at the current offset. + memcpy(buffer + bufPos, &resource, sizeof(bt_resource)); + bufPos += sizeof(bt_resource); + } + + // Copy the null terminating structure. + resource.type = B_HOST_TO_LENDIAN_INT32(BT_SHARED_NULL); + resource.name[0] = 0; + memcpy(buffer + bufPos, &resource, sizeof(bt_resource)); + bufPos += sizeof(bt_resource); + + return bufPos; +} + +// getHostInfo() +// +void getHostInfo(bt_hostinfo *info) +{ + system_info sysinfo; + bt_session_t *s; + struct utsname uts; + char buf[100]; + int i; + + struct cpuMap + { + int cpuType; + char *cpuName; + } cpuList[] = + { + { B_CPU_PPC_601, "PowerPC 601" }, + { B_CPU_PPC_603, "PowerPC 603" }, + { B_CPU_PPC_603e, "PowerPC 603e" }, + { B_CPU_PPC_604, "PowerPC 604" }, + { B_CPU_PPC_604e, "PowerPC 604e" }, + { B_CPU_PPC_750, "PowerPC 750" }, + { B_CPU_PPC_686, "PowerPC 686" }, + + { B_CPU_INTEL_X86, "Intel 80x86" }, + { B_CPU_INTEL_PENTIUM, "Intel Pentium" }, + { B_CPU_INTEL_PENTIUM75, "Intel Pentium" }, + { B_CPU_INTEL_PENTIUM_486_OVERDRIVE, "Intel 486 Overdrive" }, + { B_CPU_INTEL_PENTIUM_MMX, "Intel Pentium MMX" }, + { B_CPU_INTEL_PENTIUM_MMX_MODEL_4, "Intel Pentium MMX" }, + { B_CPU_INTEL_PENTIUM_MMX_MODEL_8, "Intel Pentium MMX" }, + { B_CPU_INTEL_PENTIUM75_486_OVERDRIVE, "Intel 486 Overdrive" }, + { B_CPU_INTEL_PENTIUM_PRO, "Intel Pentium Pro" }, + { B_CPU_INTEL_PENTIUM_II, "Intel Pentium II" }, + { B_CPU_INTEL_PENTIUM_II_MODEL_3, "Intel Pentium II" }, + { B_CPU_INTEL_PENTIUM_II_MODEL_5, "Intel Pentium II" }, + { B_CPU_INTEL_CELERON, "Intel Celeron" }, + { B_CPU_INTEL_PENTIUM_III, "Intel Pentium III" }, + + { B_CPU_AMD_X86, "AMD x86" }, + { B_CPU_AMD_K5_MODEL0, "AMD K5" }, + { B_CPU_AMD_K5_MODEL1, "AMD K5" }, + { B_CPU_AMD_K5_MODEL2, "AMD K5" }, + { B_CPU_AMD_K5_MODEL3, "AMD K5" }, + { B_CPU_AMD_K6_MODEL6, "AMD K6" }, + { B_CPU_AMD_K6_MODEL7, "AMD K6" }, + { B_CPU_AMD_K6_MODEL8, "AMD K6" }, + { B_CPU_AMD_K6_2, "AMD K6-2" }, + { B_CPU_AMD_K6_MODEL9, "AMD K6" }, + { B_CPU_AMD_K6_III, "AMD K6-3" }, + { B_CPU_AMD_ATHLON_MODEL1, "AMD Athlon" }, + + { B_CPU_CYRIX_X86, "Cyrix x86" }, + { B_CPU_CYRIX_GXm, "Cyrix GXm" }, + { B_CPU_CYRIX_6x86MX, "Cyrix 6x86MX" }, + + { B_CPU_IDT_X86, "IDT x86" }, + { B_CPU_IDT_WINCHIP_C6, "IDT WinChip C6" }, + { B_CPU_IDT_WINCHIP_2, "IDT WinChip 2" }, + + { B_CPU_RISE_X86, "Rise x86" }, + { B_CPU_RISE_mP6, "Rise mP6" }, + + { 0, NULL } + }; + + uname(&uts); + get_system_info(&sysinfo); + + strcpy(info->system, uts.sysname); + strcat(info->system, " "); + strcat(info->system, uts.release); + strcpy(info->beServed, "BeServed 1.2.6"); + + info->cpus = B_HOST_TO_LENDIAN_INT32(sysinfo.cpu_count); + info->maxConnections = B_HOST_TO_LENDIAN_INT32(BT_MAX_THREADS); + + strcpy(info->platform, "Unknown"); + for (i = 0; cpuList[i].cpuType; i++) + if (cpuList[i].cpuType == sysinfo.cpu_type) + { + strcpy(info->platform, cpuList[i].cpuName); + break; + } + + sprintf(buf, " at %ldMHz", (long) (sysinfo.cpu_clock_speed / 1000000)); + strcat(info->platform, buf); + + // Delay all new session creation. + beginReading(&sessionData); + + info->connections = 0; + for (s = rootSession; s; s = s->next) + if (s->socket != INVALID_SOCKET) + info->connections++; + + info->connections = B_HOST_TO_LENDIAN_INT32(info->connections); + endReading(&sessionData); +} + +// getHostUsers() +// +int getHostUsers(char *buffer) +{ + bt_session_t *s; + char addr[20]; + int len, bufSize; + + // Initialize the buffer to be empty. + buffer[0] = 0; + bufSize = 0; + + // Delay all new session creation. + beginReading(&sessionData); + + for (s = rootSession; s; s = s->next) + if (s->socket != INVALID_SOCKET) + { + uint8 *s_addr = (uint8 *) s->client_s_addr; + sprintf(addr, "%d.%d.%d.%d", s_addr[0], s_addr[1], s_addr[2], s_addr[3]); + len = strlen(buffer); + strcpy(&buffer[len > 0 ? len + 1 : 0], addr); + bufSize += len + 1; + } + + endReading(&sessionData); + + buffer[bufSize++] = 0; + return bufSize; +} + +void initShares() +{ + FILE *fp; + char path[B_PATH_NAME_LENGTH], buffer[512]; + int i, length; + + authServerIP = 0; + authServerName[0] = 0; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + { + fileShares[i].name[0] = 0; + fileShares[i].path[0] = 0; + fileShares[i].used = false; + fileShares[i].readOnly = true; + fileShares[i].security = BT_AUTH_NONE; + fileShares[i].rights = NULL; + fileShares[i].next = NULL; + } + + find_directory(B_COMMON_SETTINGS_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/BeServed-Settings"); + + fp = fopen(path, "r"); + if (fp) + { + while (fgets(buffer, sizeof(buffer) - 1, fp)) + { + length = strlen(buffer); + if (length <= 1 || buffer[0] == '#') + continue; + + if (buffer[length - 1] == '\n') + buffer[--length] = 0; + + if (strncmp(buffer, "share ", 6) == 0) + getFileShare(buffer); + else if (strncmp(buffer, "set ", 4) == 0) + getShareProperty(buffer); + else if (strncmp(buffer, "grant ", 6) == 0) + getGrant(buffer); + else if (strncmp(buffer, "authenticate ", 13) == 0) + getAuthenticate(buffer); + } + + fclose(fp); + } +} + +void getFileShare(const char *buffer) +{ + struct stat st; + char path[B_PATH_NAME_LENGTH], share[MAX_NAME_LENGTH + 1], *folder; + int i, tok; + + // Skip over SHARE command. + tokPtr = (char *) buffer + (6 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(path, tokBuffer); + tok = getToken(); + if (tok != BT_TOKEN_AS) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + + // Now verify that the share name specified has not already been + // used to share another path. + folder = btGetSharePath(share); + if (folder) + { + syslog(LOG_WARNING, "%s already defined as %s\n", share, folder); + return; + } + + // Check the path to ensure its validity. + if (stat(path, &st) != 0) + return; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (!fileShares[i].used) + { + syslog(LOG_INFO, "Defining %s as %s\n", share, path); + strcpy(fileShares[i].name, share); + strcpy(fileShares[i].path, path); + fileShares[i].used = true; + return; + } + + syslog(LOG_WARNING, "Share %s could not be defined (too many shares)\n", share); +} + +void getShareProperty(const char *buffer) +{ + char share[B_FILE_NAME_LENGTH + 1]; + int tok, shareId; + + // Skip over SET command. + tokPtr = (char *) buffer + (4 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + + // Get the index of the share referred to. If the named share cannot be + // found, then abort. + shareId = btGetShareId(share); + if (shareId < 0) + return; + + tok = getToken(); + if (tok == BT_TOKEN_READWRITE) + { + fileShares[shareId].readOnly = false; + syslog(LOG_INFO, "%s permits writing\n", share); + } +} + +void getGrant(const char *buffer) +{ + char share[MAX_NAME_LENGTH + 1]; + int tok, rights; + bool isGroup = false; + + // Skip over GRANT command. + tokPtr = (char *) buffer + (6 * sizeof(char)); + rights = 0; + + do + { + tok = getToken(); + if (tok == BT_TOKEN_READ) + { + rights |= BT_RIGHTS_READ; + tok = getToken(); + } + else if (tok == BT_TOKEN_WRITE) + { + rights |= BT_RIGHTS_WRITE; + tok = getToken(); + } + } while (tok == BT_TOKEN_COMMA); + + if (tok != BT_TOKEN_ON) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + tok = getToken(); + if (tok != BT_TOKEN_TO) + return; + + tok = getToken(); + if (tok == BT_TOKEN_GROUP) + { + isGroup = true; + tok = getToken(); + } + + if (tok != BT_TOKEN_STRING) + return; + + addUserRights(share, tokBuffer, rights, isGroup); +} + +void getAuthenticate(const char *buffer) +{ + struct hostent *ent; + int i, tok; + + // Skip over AUTHENTICATE command. + tokPtr = (char *) buffer + (13 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_WITH) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + // Look up address for given host. + getAuthServerAddress(tokBuffer); + + // Make all file shares use BeSure authentication. + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + fileShares[i].security = BT_AUTH_BESURE; + + syslog(LOG_INFO, "Using authentication server at %s\n", tokBuffer); +} + +bool getAuthServerAddress(const char *name) +{ + // Look up address for given host. + struct hostent *ent = gethostbyname(name); + if (ent == NULL) + { + syslog(LOG_ERR, "Authentication server %s is unavailable.\n", name); + return false; + } + + strcpy(authServerName, name); + authServerIP = ntohl(*((unsigned int *) ent->h_addr)); + return true; +} + +void addUserRights(char *share, char *user, int rights, bool isGroup) +{ + bt_user_rights *ur; + int shareId; + + shareId = btGetShareId(share); + if (shareId < 0) + return; + + ur = (bt_user_rights *) malloc(sizeof(bt_user_rights)); + if (ur) + { + ur->user = (char *) malloc(strlen(user) + 1); + if (ur->user) + { + strcpy(ur->user, user); + ur->rights = rights; + ur->isGroup = isGroup; + ur->next = fileShares[shareId].rights; + fileShares[shareId].rights = ur; + } + else + free(ur); + } +} + +int getToken() +{ + bool quoted = false; + + tokBuffer[0] = 0; + while (*tokPtr && iswhite(*tokPtr)) + tokPtr++; + + if (*tokPtr == ',') + { + tokPtr++; + return BT_TOKEN_COMMA; + } + else if (*tokPtr == '\"') + { + quoted = true; + tokPtr++; + } + + if (isalnum(*tokPtr) || *tokPtr == '/') + { + int i = 0; + while (isalnum(*tokPtr) || isValid(*tokPtr) || (quoted && *tokPtr == ' ')) + if (i < B_PATH_NAME_LENGTH) + tokBuffer[i++] = *tokPtr++; + else + tokPtr++; + + tokBuffer[i] = 0; + + if (!quoted) + for (i = 0; keywords[i]; i++) + if (strcasecmp(tokBuffer, keywords[i]) == 0) + return ++i; + + if (quoted) + if (*tokPtr != '\"') + return BT_TOKEN_ERROR; + else + tokPtr++; + + return BT_TOKEN_STRING; + } + + return BT_TOKEN_ERROR; +} + +void startService() +{ + struct sockaddr_in serverAddr, clientAddr; + int client, addrLen; + int flags; + + // Store the length of the socket addressing structure for accept(). + addrLen = sizeof(struct sockaddr_in); + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(BT_TCPIP_PORT); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Create a new socket to receive incoming requests. + server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (server == INVALID_SOCKET) + return; + + // Set the socket option to reuse the current address in case it was + // in use by a prior version of the service that has not yet relinquished + // the socket. + flags = 1; + setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); + + // Bind that socket to the address constructed above. + if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return; + + // Listen for incoming connections. + if (listen(server, 5)) + return; + + // Continually accept incoming connections. When one is found, + // fire off a handler thread to accept commands. + while (running) + { + client = accept(server, (struct sockaddr *) &clientAddr, &addrLen); + if (client != INVALID_SOCKET) + launchThread(client, &clientAddr); + } + + // Close the socket. Technically, I believe we should call shutdown() + // first, but the BeOS header file socket.h indicates that this + // function is not currently working. It is present but may not have + // any effect. + shutdown(server, 2); + closesocket(server); + server = INVALID_SOCKET; +} + +void endService(int sig) +{ + // Close the syslog. + closelog(); + + if (hostThread > 0) + kill_thread(hostThread); + + closeManagedData(&sessionData); + closeManagedData(&handleData); + + freeFileHandles(); + freeFileShares(); + + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + exit(0); +} + +// freeFileHandles() +// +void freeFileHandles() +{ + bt_node *nextNode, *curNode = rootNode; + + while (curNode) + { + nextNode = curNode->next; + free(curNode); + curNode = nextNode; + } +} + +// freeFileShares() +// +void freeFileShares() +{ + bt_user_rights *ur, *nextUr; + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + for (ur = fileShares[i].rights; ur; ) + { + nextUr = ur->next; + if (ur->user) + free(ur->user); + + free(ur); + ur = nextUr; + } +} + +// launchThread() +// +void launchThread(int client, struct sockaddr_in *addr) +{ + bt_session_t *s, *cur, *last = NULL; + int count = 0; + + // First verify that the server's not too busy by scanning the list of active + // sessions. This is also useful because we need to eliminate unused sessions + // from the list, i.e., sessions that have closed. + beginWriting(&sessionData); + + s = rootSession; + while (s) + { + if (s->socket == INVALID_SOCKET) + { + if (last) + last->next = s->next; + else + rootSession = s->next; + + cur = s->next; + free(s); + s = cur; + continue; + } + + last = s; + s = s->next; + count++; + } + + // If the total number of valid sessions was less than our allowed maximum, then + // we can create a new session. + if (count < BT_MAX_THREADS) + { + // We need to create an available session for this connection. + bt_session_t *session = (bt_session_t *) malloc(sizeof(bt_session_t)); + if (session) + { + session->socket = client; + session->client_s_addr = addr->sin_addr.s_addr; + session->rootBlock = NULL; + session->killed = false; + session->rights = 0; + + session->handlerID = + spawn_thread(requestThread, BT_THREAD_NAME, B_NORMAL_PRIORITY, session); + resume_thread(session->handlerID); + + // Add this to the session list. + session->next = rootSession; + rootSession = session; + endWriting(&sessionData); + return; + } + } + + endWriting(&sessionData); + + // We must have too many threads active, so let the client know we're busy. + sendErrorToClient(client, 0, EBUSY); + shutdown(client, 2); + closesocket(client); +} + +int32 requestThread(void *data) +{ + bt_session_t *session = (bt_session_t *) data; +// int flags; + + if (!session) + return 0; + + // Ensure that this connection remains alive. If a periodic message (handled by the OS) + // fails, then blocked socket calls are interrupted and return with a ESIGPIPE error. +// flags = 1; +// setsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags)); + + if ((session->blockSem = create_sem(0, "Gathered Write Semaphore")) > B_OK) + { + while (!session->killed && receiveRequest(session)); + delete_sem(session->blockSem); + } + + shutdown(session->socket, 2); + closesocket(session->socket); + session->socket = INVALID_SOCKET; + return 0; +} + +int receiveRequest(bt_session_t *session) +{ + bt_inPacket packet; + char signature[20], *buffer; + unsigned char command; + int client, sigLen; + int32 length; + + client = session->socket; + + // Read the BeTalk RPC header. + sigLen = strlen(BT_RPC_SIGNATURE); + if (btRecvMsg(client, signature, sigLen, 0) == -1) + return 0; +// recv(client, &verHi, sizeof(verHi), 0); +// recv(client, &verLo, sizeof(verLo), 0); + + signature[sigLen] = 0; + if (strcmp(signature, BT_RPC_SIGNATURE)) + return 0; + + // Read in the rest of the packet. + if (btRecvMsg(client, &length, sizeof(int32), 0) == -1) + return 0; + + length = B_LENDIAN_TO_HOST_INT32(length); + if (length == 0 || length > BT_RPC_MAX_PACKET_SIZE) + return 0; + + buffer = (char *) malloc(length + 1); + if (!buffer) + return 0; + + if (btRecvMsg(client, buffer, length, 0) == -1) + { + free(buffer); + return 0; + } + + buffer[length] = 0; + packet.buffer = buffer; + packet.length = length; + packet.offset = 0; + + // Read the transmission ID and command. + command = btRPCGetChar(&packet); + getArguments(session, &packet, command); + free(buffer); + return (command != BT_CMD_QUIT && command != BT_CMD_PREMOUNT); +} + +void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command) +{ + bt_arg_t args[MAX_COMMAND_ARGS]; + int i, client; + bool error; + unsigned char argc, terminator; + int32 xid; + + error = false; + client = session->socket; + argc = btRPCGetChar(packet); + if (argc > MAX_COMMAND_ARGS) + return; + + for (i = 0; i < argc && !error; i++) + { + args[i].type = btRPCGetInt32(packet); + args[i].data = btRPCGetNewString(packet); + if (args[i].data == NULL) + error = true; + } + + if (!error) + { + xid = btRPCGetInt32(packet); + terminator = btRPCGetChar(packet); + if (terminator == BT_CMD_TERMINATOR) + handleRequest(session, xid, command, argc, args); + } + else + sendErrorToClient(session->socket, 0, EINVAL); + + while (--i >= 0) + free(args[i].data); +} + +void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]) +{ + bool validated = true; + int i, j; + + for (i = 0; dirCommands[i].handler; i++) + if (command == dirCommands[i].command) + { + // We may have received a valid command, but one that is not supported by this + // server. In this case, we'll want to return an operation not supported error, + // as opposed to an invalid command error. + if (!dirCommands[i].supported) + { + sendErrorToClient(session->socket, xid, EOPNOTSUPP); + return; + } + + // Now verify that the argument count is correct, and if so, the type of all + // arguments is correct. If not, an invalid command error is returned. + // Otherise, the command is executed, and the handler returns any necessary + // acknowledgement. + if (argc == dirCommands[i].args) + { + for (j = 0; j < argc; j++) + if (dirCommands[i].argTypes[j] != argv[j].type) + { + validated = false; + break; + } + + if (validated) + { + (*dirCommands[i].handler)(session, xid, argc, argv); + return; + } + } + } + + sendErrorToClient(session->socket, xid, EINVAL); +} + +void sendErrorToClient(int client, unsigned int xid, int error) +{ + bt_outPacket packet; + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +int btRecvMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesRead = 0; + do + { + int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags); + if (bytes == -1) + return -1; + + bytesRead += bytes; + } while (bytesRead < dataLen); + + return bytesRead; +} + +// btRecv() +// +int btRecv(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = recv(sock, data, dataLen, flags); + if (bytes == 0) + return -1; + else if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +int btSendMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesSent = 0; + do + { + int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags); + if (bytes == -1) + return -1; + + bytesSent += bytes; + } while (bytesSent < dataLen); + + return bytesSent; +} + +// btSend() +// +int btSend(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = send(sock, data, dataLen, flags); + if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error) +{ + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + return; + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + btRPCPutInt32(packet, xid); + btRPCPutInt32(packet, 0); + btRPCPutInt32(packet, error); +} + +void btRPCSendAck(int client, bt_outPacket *packet) +{ + if (packet) + if (packet->buffer) + { + *(int32 *)(&packet->buffer[9]) = packet->length - 13; + btSendMsg(client, packet->buffer, packet->length, 0); + free(packet->buffer); + } +} + +unsigned char btRPCGetChar(bt_inPacket *packet) +{ + unsigned char value; + + if (packet->offset < packet->length) + value = (unsigned char) packet->buffer[packet->offset]; + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + if (bytes > 0) + memcpy(str, &packet->buffer[packet->offset], bytes); + + str[bytes] = 0; + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return ERANGE; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return ERANGE; + + if (length < bytes) + return ERANGE; + + if (bytes > 0) + memcpy(buffer, &packet->buffer[packet->offset], bytes); + + packet->offset += bytes; + return bytes; +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +int btRPCGetStat(bt_inPacket *packet, struct stat *st) +{ + st->st_dev = 0; + st->st_nlink = btRPCGetInt32(packet); + st->st_uid = btRPCGetInt32(packet); + st->st_gid = btRPCGetInt32(packet); + st->st_size = btRPCGetInt64(packet); + st->st_blksize = btRPCGetInt32(packet); + st->st_rdev = btRPCGetInt32(packet); + st->st_ino = btRPCGetInt64(packet); + st->st_mode = btRPCGetInt32(packet); + st->st_atime = btRPCGetInt32(packet); + st->st_mtime = btRPCGetInt32(packet); + st->st_ctime = btRPCGetInt32(packet); +} + +void btRPCPutStat(bt_outPacket *packet, struct stat *st) +{ + if (packet && st) + { + btRPCPutInt32(packet, (int) st->st_nlink); + btRPCPutInt32(packet, (int) st->st_uid); + btRPCPutInt32(packet, (int) st->st_gid); + btRPCPutInt64(packet, (int64) st->st_size); + btRPCPutInt32(packet, (int) st->st_blksize); + btRPCPutInt32(packet, (int) st->st_rdev); + btRPCPutInt64(packet, (int64) st->st_ino); + btRPCPutInt32(packet, (int) st->st_mode); + btRPCPutInt32(packet, (int) st->st_atime); + btRPCPutInt32(packet, (int) st->st_mtime); + btRPCPutInt32(packet, (int) st->st_ctime); + } +} + +//////////////////////////////////////////////////////////////////// diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/betalk.h new file mode 100644 index 0000000000..af38d0d926 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +// The different types of network resources supported by BeServed. +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRITNER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 32768 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 128 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int nsid; + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +typedef struct rpcInfo +{ + thread_id rpcThread; + int32 quitXID; + + uint32 serverIP; + int32 serverPort; + int s; +} bt_rpcinfo; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket inPacket; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/file_shares.h b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/file_shares.h new file mode 100644 index 0000000000..573592ca7a --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/file_shares.h @@ -0,0 +1,31 @@ +#ifndef _FILE_SHARES_H_ +#define _FILE_SHARES_H_ + +#include "betalk.h" + +#define BT_MAX_FILE_SHARES 128 + +typedef struct userRights +{ + char *user; + int rights; + bool isGroup; + struct userRights *next; +} bt_user_rights; + +typedef struct fileShare +{ + char path[B_PATH_NAME_LENGTH]; + char name[B_FILE_NAME_LENGTH]; + + bool used; + bool readOnly; + + // What rights does each user have? + bt_user_rights *rights; + int security; + + struct fileShare *next; +} bt_fileShare_t; + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/fsproto.h b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/fsproto.h new file mode 100644 index 0000000000..a6072837d5 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/fsproto.h @@ -0,0 +1,246 @@ +#ifndef _FSPROTO_H +#define _FSPROTO_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef dev_t nspace_id; +typedef ino_t vnode_id; + +/* UGLY UGLY UGLY */ +#ifndef _DRIVERS_H +struct selectsync; +typedef struct selectsync selectsync; +#endif + + +/* + * PUBLIC PART OF THE FILE SYSTEM PROTOCOL + */ + +#define WSTAT_MODE 0x0001 +#define WSTAT_UID 0x0002 +#define WSTAT_GID 0x0004 +#define WSTAT_SIZE 0x0008 +#define WSTAT_ATIME 0x0010 +#define WSTAT_MTIME 0x0020 +#define WSTAT_CRTIME 0x0040 + +#define WFSSTAT_NAME 0x0001 + +#define B_ENTRY_CREATED 1 +#define B_ENTRY_REMOVED 2 +#define B_ENTRY_MOVED 3 +#define B_STAT_CHANGED 4 +#define B_ATTR_CHANGED 5 +#define B_DEVICE_MOUNTED 6 +#define B_DEVICE_UNMOUNTED 7 + +#define B_STOP_WATCHING 0x0000 +#define B_WATCH_NAME 0x0001 +#define B_WATCH_STAT 0x0002 +#define B_WATCH_ATTR 0x0004 +#define B_WATCH_DIRECTORY 0x0008 + +#define SELECT_READ 1 +#define SELECT_WRITE 2 +#define SELECT_EXCEPTION 3 + +#define B_CUR_FS_API_VERSION 2 + +struct attr_info; +struct index_info; + +typedef int op_read_vnode(void *ns, vnode_id vnid, char r, void **node); +typedef int op_write_vnode(void *ns, void *node, char r); +typedef int op_remove_vnode(void *ns, void *node, char r); +typedef int op_secure_vnode(void *ns, void *node); + +typedef int op_walk(void *ns, void *base, const char *file, char **newpath, + vnode_id *vnid); + +typedef int op_access(void *ns, void *node, int mode); + +typedef int op_create(void *ns, void *dir, const char *name, + int omode, int perms, vnode_id *vnid, void **cookie); +typedef int op_mkdir(void *ns, void *dir, const char *name, int perms); +typedef int op_symlink(void *ns, void *dir, const char *name, + const char *path); +typedef int op_link(void *ns, void *dir, const char *name, void *node); + +typedef int op_rename(void *ns, void *olddir, const char *oldname, + void *newdir, const char *newname); +typedef int op_unlink(void *ns, void *dir, const char *name); +typedef int op_rmdir(void *ns, void *dir, const char *name); + +typedef int op_readlink(void *ns, void *node, char *buf, size_t *bufsize); + +typedef int op_opendir(void *ns, void *node, void **cookie); +typedef int op_closedir(void *ns, void *node, void *cookie); +typedef int op_rewinddir(void *ns, void *node, void *cookie); +typedef int op_readdir(void *ns, void *node, void *cookie, long *num, + struct dirent *buf, size_t bufsize); + +typedef int op_open(void *ns, void *node, int omode, void **cookie); +typedef int op_close(void *ns, void *node, void *cookie); +typedef int op_free_cookie(void *ns, void *node, void *cookie); +typedef int op_read(void *ns, void *node, void *cookie, off_t pos, void *buf, + size_t *len); +typedef int op_write(void *ns, void *node, void *cookie, off_t pos, + const void *buf, size_t *len); +typedef int op_readv(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, + size_t count, size_t *len); +typedef int op_writev(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, + size_t count, size_t *len); +typedef int op_ioctl(void *ns, void *node, void *cookie, int cmd, void *buf, + size_t len); +typedef int op_setflags(void *ns, void *node, void *cookie, int flags); + +typedef int op_rstat(void *ns, void *node, struct stat *); +typedef int op_wstat(void *ns, void *node, struct stat *, long mask); +typedef int op_fsync(void *ns, void *node); + +typedef int op_select(void *ns, void *node, void *cookie, uint8 event, + uint32 ref, selectsync *sync); +typedef int op_deselect(void *ns, void *node, void *cookie, uint8 event, + selectsync *sync); + +typedef int op_initialize(const char *devname, void *parms, size_t len); +typedef int op_mount(nspace_id nsid, const char *devname, ulong flags, + void *parms, size_t len, void **data, vnode_id *vnid); +typedef int op_unmount(void *ns); +typedef int op_sync(void *ns); +typedef int op_rfsstat(void *ns, struct fs_info *); +typedef int op_wfsstat(void *ns, struct fs_info *, long mask); + + +typedef int op_open_attrdir(void *ns, void *node, void **cookie); +typedef int op_close_attrdir(void *ns, void *node, void *cookie); +typedef int op_rewind_attrdir(void *ns, void *node, void *cookie); +typedef int op_read_attrdir(void *ns, void *node, void *cookie, long *num, + struct dirent *buf, size_t bufsize); +typedef int op_remove_attr(void *ns, void *node, const char *name); +typedef int op_rename_attr(void *ns, void *node, const char *oldname, + const char *newname); +typedef int op_stat_attr(void *ns, void *node, const char *name, + struct attr_info *buf); + +typedef int op_write_attr(void *ns, void *node, const char *name, int type, + const void *buf, size_t *len, off_t pos); +typedef int op_read_attr(void *ns, void *node, const char *name, int type, + void *buf, size_t *len, off_t pos); + +typedef int op_open_indexdir(void *ns, void **cookie); +typedef int op_close_indexdir(void *ns, void *cookie); +typedef int op_rewind_indexdir(void *ns, void *cookie); +typedef int op_read_indexdir(void *ns, void *cookie, long *num, + struct dirent *buf, size_t bufsize); +typedef int op_create_index(void *ns, const char *name, int type, int flags); +typedef int op_remove_index(void *ns, const char *name); +typedef int op_rename_index(void *ns, const char *oldname, + const char *newname); +typedef int op_stat_index(void *ns, const char *name, struct index_info *buf); + +typedef int op_open_query(void *ns, const char *query, ulong flags, + port_id port, long token, void **cookie); +typedef int op_close_query(void *ns, void *cookie); +typedef int op_read_query(void *ns, void *cookie, long *num, + struct dirent *buf, size_t bufsize); + +typedef struct vnode_ops { + op_read_vnode (*read_vnode); + op_write_vnode (*write_vnode); + op_remove_vnode (*remove_vnode); + op_secure_vnode (*secure_vnode); + op_walk (*walk); + op_access (*access); + op_create (*create); + op_mkdir (*mkdir); + op_symlink (*symlink); + op_link (*link); + op_rename (*rename); + op_unlink (*unlink); + op_rmdir (*rmdir); + op_readlink (*readlink); + op_opendir (*opendir); + op_closedir (*closedir); + op_free_cookie (*free_dircookie); + op_rewinddir (*rewinddir); + op_readdir (*readdir); + op_open (*open); + op_close (*close); + op_free_cookie (*free_cookie); + op_read (*read); + op_write (*write); + op_readv (*readv); + op_writev (*writev); + op_ioctl (*ioctl); + op_setflags (*setflags); + op_rstat (*rstat); + op_wstat (*wstat); + op_fsync (*fsync); + op_initialize (*initialize); + op_mount (*mount); + op_unmount (*unmount); + op_sync (*sync); + op_rfsstat (*rfsstat); + op_wfsstat (*wfsstat); + op_select (*select); + op_deselect (*deselect); + op_open_indexdir (*open_indexdir); + op_close_indexdir (*close_indexdir); + op_free_cookie (*free_indexdircookie); + op_rewind_indexdir (*rewind_indexdir); + op_read_indexdir (*read_indexdir); + op_create_index (*create_index); + op_remove_index (*remove_index); + op_rename_index (*rename_index); + op_stat_index (*stat_index); + op_open_attrdir (*open_attrdir); + op_close_attrdir (*close_attrdir); + op_free_cookie (*free_attrdircookie); + op_rewind_attrdir (*rewind_attrdir); + op_read_attrdir (*read_attrdir); + op_write_attr (*write_attr); + op_read_attr (*read_attr); + op_remove_attr (*remove_attr); + op_rename_attr (*rename_attr); + op_stat_attr (*stat_attr); + op_open_query (*open_query); + op_close_query (*close_query); + op_free_cookie (*free_querycookie); + op_read_query (*read_query); +} vnode_ops; + +extern _IMPEXP_KERNEL int new_path(const char *path, char **copy); +extern _IMPEXP_KERNEL void free_path(char *p); + +extern _IMPEXP_KERNEL int notify_listener(int op, nspace_id nsid, + vnode_id vnida, vnode_id vnidb, + vnode_id vnidc, const char *name); +extern _IMPEXP_KERNEL void notify_select_event(selectsync *sync, uint32 ref); +extern _IMPEXP_KERNEL int send_notification(port_id port, long token, + ulong what, long op, nspace_id nsida, + nspace_id nsidb, vnode_id vnida, + vnode_id vnidb, vnode_id vnidc, + const char *name); +extern _IMPEXP_KERNEL int get_vnode(nspace_id nsid, vnode_id vnid, void **data); +extern _IMPEXP_KERNEL int put_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int new_vnode(nspace_id nsid, vnode_id vnid, void *data); +extern _IMPEXP_KERNEL int remove_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int unremove_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int is_vnode_removed(nspace_id nsid, vnode_id vnid); + + +extern _EXPORT vnode_ops fs_entry; +extern _EXPORT int32 api_version; + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/readerWriter.c b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/readerWriter.c new file mode 100644 index 0000000000..c98609bde9 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/readerWriter.c @@ -0,0 +1,127 @@ +// readerWriter.c + +#include "betalk.h" +#include "readerWriter.h" + + +void btLock(sem_id semaphore, int32 *atomic) +{ + int32 previous = atomic_add(atomic, 1); + if (previous >= 1) + while (acquire_sem(semaphore) == B_INTERRUPTED); +} + +void btUnlock(sem_id semaphore, int32 *atomic) +{ + int32 previous = atomic_add(atomic, -1); + if (previous > 1) + release_sem(semaphore); +} + +bool initManagedData(bt_managed_data *data) +{ + data->readCount = 0; + data->writeCount = 0; + + data->readCountVar = 0; + data->writeCountVar = 0; + data->readerQueueVar = 0; + data->readerVar = 0; + data->writerVar = 0; + + if ((data->readCountSem = create_sem(1, "Read Counter")) < 0) + return false; + + if ((data->writeCountSem = create_sem(1, "Write Counter")) < 0) + { + delete_sem(data->readCountSem); + return false; + } + + if ((data->readerQueue = create_sem(1, "Read Queue")) < 0) + { + delete_sem(data->writeCountSem); + delete_sem(data->readCountSem); + return false; + } + + if ((data->reader = create_sem(1, "Single Reader")) < 0) + { + delete_sem(data->readerQueue); + delete_sem(data->writeCountSem); + delete_sem(data->readCountSem); + return false; + } + + if ((data->writer = create_sem(1, "Writer")) < 0) + { + delete_sem(data->reader); + delete_sem(data->readerQueue); + delete_sem(data->writeCountSem); + delete_sem(data->readCountSem); + return false; + } + + return true; +} + +void closeManagedData(bt_managed_data *data) +{ + data->readCount = data->writeCount = 0; + + delete_sem(data->writer); + delete_sem(data->reader); + delete_sem(data->readerQueue); + delete_sem(data->writeCountSem); + delete_sem(data->readCountSem); +} + +void beginReading(bt_managed_data *data) +{ + btLock(data->readerQueue, &data->readerQueueVar); + btLock(data->reader, &data->readerVar); + btLock(data->readCountSem, &data->readCountVar); + + data->readCount++; + if (data->readCount == 1) + btLock(data->writer, &data->writerVar); + + btUnlock(data->readCountSem, &data->readCountVar); + btUnlock(data->reader, &data->readerVar); + btUnlock(data->readerQueue, &data->readerQueueVar); +} + +void endReading(bt_managed_data *data) +{ + btLock(data->readCountSem, &data->readCountVar); + + data->readCount--; + if (data->readCount == 0) + btUnlock(data->writer, &data->writerVar); + + btUnlock(data->readCountSem, &data->readCountVar); +} + +void beginWriting(bt_managed_data *data) +{ + btLock(data->writeCountSem, &data->writeCountVar); + + data->writeCount++; + if (data->writeCount == 1) + btLock(data->reader, &data->readerVar); + + btUnlock(data->writeCountSem, &data->writeCountVar); + btLock(data->writer, &data->writerVar); +} + +void endWriting(bt_managed_data *data) +{ + btUnlock(data->writer, &data->writerVar); + btLock(data->writeCountSem, &data->writeCountVar); + + data->writeCount--; + if (data->writeCount == 0) + btUnlock(data->reader, &data->readerVar); + + btUnlock(data->writeCountSem, &data->writeCountVar); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/readerWriter.h b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/readerWriter.h new file mode 100644 index 0000000000..53b1ac117f --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/readerWriter.h @@ -0,0 +1,36 @@ +// readerWriter.h + +#include "betalk.h" + +typedef struct managedData +{ + int32 readCount; + int32 writeCount; + + // These two semaphores control access to the readCount and writeCount + // variables. + sem_id readCountSem; + int32 readCountVar; + sem_id writeCountSem; + int32 writeCountVar; + + // The first process wishes to gain read access blocks on the reader + // semaphore, but all other block on the readerQueue, so that writers + // can effectively jump the queue. + sem_id readerQueue; + int32 readerQueueVar; + + // Semaphores for holding waiting processes. + sem_id reader; + int32 readerVar; + sem_id writer; + int32 writerVar; +} bt_managed_data; + + +bool initManagedData(bt_managed_data *data); +void closeManagedData(bt_managed_data *data); +void beginReading(bt_managed_data *data); +void endReading(bt_managed_data *data); +void beginWriting(bt_managed_data *data); +void endWriting(bt_managed_data *data); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_handlers.c b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_handlers.c new file mode 100644 index 0000000000..6887f18c63 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_handlers.c @@ -0,0 +1,749 @@ +#include "betalk.h" +#include "sessions.h" +#include "rpc_handlers.h" +#include "rpc_workers.h" +#include "file_shares.h" + +extern bt_fileShare_t fileShares[]; + + +void netbtPreMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, security; + + client = session->socket; + security = btPreMount(session, argv[0].data); + btRPCCreateAck(&packet, xid, security); + btRPCSendAck(client, &packet); +} + +void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + vnode_id vnid; + int client, error; + char *shareName = argv[0].data; + char *user = argv[1].data; + char *password = argv[2].data; + + client = session->socket; + error = btMount(session, shareName, user, password, &vnid); + if (error == B_OK) + { + // Record this session having logged in to a specific share. + session->share = btGetShareId(shareName); + session->logon = time(NULL); + + // Now send the client a response with the root vnid. + btRPCCreateAck(&packet, xid, error); + btRPCPutInt64(&packet, vnid); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + fs_info info; + int client, error; + + client = session->socket; + + error = btGetFSInfo(fileShares[session->share].path, &info); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCPutInt32(&packet, info.block_size); + btRPCPutInt32(&packet, info.total_blocks); + btRPCPutInt32(&packet, info.free_blocks); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + struct stat st; + int client, error; + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + + client = session->socket; + error = btLookup(session->pathBuffer, dir_vnid, argv[1].data, &file_vnid); + if (error == B_OK) + error = btStat(session->pathBuffer, file_vnid, &st); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt64(&packet, file_vnid); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + struct stat st; + int client, error; + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + DIR *dir; + char filename[B_PATH_NAME_LENGTH]; + int entries = 0; + + client = session->socket; + + dir = (DIR *)(*((int32 *) argv[1].data)); + error = btReadDir(session->pathBuffer, dir_vnid, &dir, &file_vnid, filename, &st); + + if (error != B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + btRPCCreateAck(&packet, xid, B_OK); + while (error == B_OK) + { + btRPCPutInt64(&packet, file_vnid); + btRPCPutString(&packet, filename, strlen(filename)); + btRPCPutInt32(&packet, (int32) dir); + btRPCPutStat(&packet, &st); + + if (++entries >= 32) + break; + + error = btReadDir(session->pathBuffer, dir_vnid, &dir, &file_vnid, filename, &st); + btRPCPutInt32(&packet, error); + } + + // If we exhausted the list of directory entries without filling + // the buffer, add an error message that will prevent the client + // from requesting further entries. + if (entries < 32) + btRPCPutInt32(&packet, ENOENT); + + btRPCSendAck(client, &packet); +} + +void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + struct stat info; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + error = btStat(session->pathBuffer, vnid, &info); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCPutStat(&packet, &info); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + vnode_id vnid = *((vnode_id *) argv[0].data); + off_t pos = *((off_t *) argv[1].data); + int32 len = *((int32 *) argv[2].data); + int32 bytes = 0; + + client = session->socket; + session->ioBuffer[len] = 0; + bytes = btRead(session->pathBuffer, vnid, pos, len, session->ioBuffer); + + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutString(&packet, session->ioBuffer, bytes); + btRPCSendAck(client, &packet); +} + +void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + vnode_id vnid = *((vnode_id *) argv[0].data); + off_t pos = *((off_t *) argv[1].data); + int32 len = *((int32 *) argv[2].data); + int32 totalLen = *((int32 *) argv[3].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (session->rights & BT_RIGHTS_WRITE) + btWrite(session, vnid, pos, len, totalLen, argv[4].data); +} + +void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + struct stat st; + int client, error; + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + int omode = *((int *) argv[2].data); + int perms = *((int *) argv[3].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btCreate(session->pathBuffer, dir_vnid, argv[1].data, omode, perms, &file_vnid); + if (error == B_OK) + error = btStat(session->pathBuffer, file_vnid, &st); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt64(&packet, file_vnid); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btTruncate(session->pathBuffer, vnid, *((int64 *) argv[1].data)); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btUnlink(session->pathBuffer, vnid, argv[1].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id old_vnid = *((vnode_id *) argv[0].data); + vnode_id new_vnid = *((vnode_id *) argv[2].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btRename(session->pathBuffer, old_vnid, argv[1].data, new_vnid, argv[3].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + struct stat st; + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btCreateDir(session->pathBuffer, dir_vnid, argv[1].data, *((int *) argv[2].data), &file_vnid, &st); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt64(&packet, file_vnid); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btDeleteDir(session->pathBuffer, vnid, argv[1].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + char path[B_PATH_NAME_LENGTH]; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + error = btReadLink(session->pathBuffer, vnid, path, B_PATH_NAME_LENGTH); + if (error == B_OK) + { + int length = strlen(path); + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutString(&packet, path, length); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btSymLink(session->pathBuffer, vnid, argv[1].data, argv[2].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + int32 mask = *((int32 *) argv[1].data); + int32 mode = *((int32 *) argv[2].data); + int32 uid = *((int32 *) argv[3].data); + int32 gid = *((int32 *) argv[4].data); + int64 size = (int64) *((int32 *) argv[5].data); + int32 atime = *((int32 *) argv[6].data); + int32 mtime = *((int32 *) argv[7].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btWStat(session->pathBuffer, vnid, mask, mode, uid, gid, size, atime, mtime); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, bytesRead; + char *buffer; + vnode_id vnid = *((vnode_id *) argv[0].data); + int32 type = *((int32 *) argv[2].data); + int32 pos = *((int32 *) argv[3].data); + int32 len = *((int32 *) argv[4].data); + + client = session->socket; + + if (len <= BT_MAX_ATTR_BUFFER) + buffer = session->attrBuffer; + else + buffer = (char *) malloc(len + 1); + + if (buffer) + { + bytesRead = btReadAttrib(session->pathBuffer, vnid, argv[1].data, type, buffer, pos, len); + if (bytesRead >= 0) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt32(&packet, (int32) bytesRead); + if (bytesRead > 0) + btRPCPutString(&packet, buffer, bytesRead); + } + else + btRPCCreateAck(&packet, xid, B_ENTRY_NOT_FOUND); + + if (len > BT_MAX_ATTR_BUFFER) + free(buffer); + } + else + btRPCCreateAck(&packet, xid, ENOMEM); + + btRPCSendAck(client, &packet); +} + +void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, bytesWritten; + vnode_id vnid = *((vnode_id *) argv[0].data); + int32 type = *((int32 *) argv[2].data); + int32 pos = *((int32 *) argv[4].data); + int32 len = *((int32 *) argv[5].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + bytesWritten = btWriteAttrib(session->pathBuffer, vnid, argv[1].data, type, argv[3].data, pos, len); + if (bytesWritten >= 0) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt32(&packet, (int32) bytesWritten); + } + else + btRPCCreateAck(&packet, xid, B_ENTRY_NOT_FOUND); + + btRPCSendAck(client, &packet); +} + +void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + DIR *dir = (DIR *)(*((int32 *) argv[1].data)); + char attrName[100]; + int entries = 0; + + client = session->socket; + + error = btReadAttribDir(session->pathBuffer, vnid, &dir, attrName); + + if (error != B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + btRPCCreateAck(&packet, xid, B_OK); + while (error == B_OK) + { + btRPCPutString(&packet, attrName, strlen(attrName)); + btRPCPutInt32(&packet, (int32) dir); + + if (++entries >= 32) + break; + + error = btReadAttribDir(session->pathBuffer, vnid, &dir, attrName); + btRPCPutInt32(&packet, error); + } + + if (entries < 32) + btRPCPutInt32(&packet, ENOENT); + + btRPCSendAck(client, &packet); +} + +void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btRemoveAttrib(session->pathBuffer, vnid, argv[1].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + struct attr_info info; + + client = session->socket; + + error = btStatAttrib(session->pathBuffer, vnid, argv[1].data, &info); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt32(&packet, info.type); + btRPCPutInt64(&packet, info.size); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + DIR *dir; + char indexName[100]; + + client = session->socket; + + dir = (DIR *)(*((int32 *) argv[0].data)); + + error = btReadIndexDir(fileShares[session->share].path, &dir, indexName); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutString(&packet, indexName, strlen(indexName)); + btRPCPutInt32(&packet, (int32) dir); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + int type = *((int32 *) argv[1].data); + int flags = *((int32 *) argv[2].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btCreateIndex(fileShares[session->share].path, argv[0].data, type, flags); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btRemoveIndex(fileShares[session->share].path, argv[0].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + struct index_info info; + + client = session->socket; + + error = btStatIndex(fileShares[session->share].path, argv[0].data, &info); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt32(&packet, info.type); + btRPCPutInt64(&packet, info.size); + btRPCPutInt32(&packet, info.modification_time); + btRPCPutInt32(&packet, info.creation_time); + btRPCPutInt32(&packet, info.uid); + btRPCPutInt32(&packet, info.gid); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + DIR *dir; + char fileName[B_PATH_NAME_LENGTH]; + vnode_id vnid, parent; + + client = session->socket; + + dir = (DIR *)(*((int32 *) argv[0].data)); + + error = btReadQuery(fileShares[session->share].path, &dir, argv[1].data, fileName, &vnid, &parent); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt64(&packet, vnid); + btRPCPutInt64(&packet, parent); + btRPCPutString(&packet, fileName, strlen(fileName)); + btRPCPutInt32(&packet, (int32) dir); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +// netbtCommit() +// +void netbtCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btCommit(session, vnid); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtPrintJobNew(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ +} + +void netbtPrintJobData(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ +} + +void netbtPrintJobCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ +} + +void netbtAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ +} + +// netbtQuit() +// +void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, B_OK); + btRPCSendAck(client, &packet); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_handlers.h b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_handlers.h new file mode 100644 index 0000000000..846b2828b2 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_handlers.h @@ -0,0 +1,53 @@ +#ifndef _RPC_HANDLERS_H_ +#define _RPC_HANDLERS_H_ + +#include "betalk.h" +#include "sessions.h" + +typedef void (*bt_net_func)(bt_session_t *, unsigned int, int, bt_arg_t *); + +typedef struct dirCommand +{ + unsigned char command; + bt_net_func handler; + bool supported; + uint8 args; + uint32 argTypes[MAX_COMMAND_ARGS]; +} bt_command_t; + + +void netbtPreMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtPrintJobNew(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtPrintJobData(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtPrintJobCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_workers.c b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_workers.c new file mode 100644 index 0000000000..67eb85fae9 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_workers.c @@ -0,0 +1,1127 @@ +#include "betalk.h" +#include "sessions.h" +#include "file_shares.h" +#include "rpc_workers.h" +#include "authentication.h" +#include "readerWriter.h" +#include "fsproto.h" + +#include "utime.h" + +extern bt_fileShare_t fileShares[]; +extern bt_node *rootNode; +extern bt_managed_data handleData; + + +bt_node *btGetNodeFromVnid(vnode_id vnid) +{ + register bt_node *curNode = rootNode; + + while (curNode && curNode->vnid != vnid) + curNode = curNode->next; + + return curNode; +} + +// btAddHandle() +// +void btAddHandle(vnode_id dir_vnid, vnode_id file_vnid, char *name) +{ + bt_node *curNode, *dirNode; + + // We don't store the references to the current and the parent directory. + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + return; + + beginWriting(&handleData); + + // Obtain the parent node. If no parent vnid is provided, then this must be + // the root node. The parent of the root node is NULL, but it should be the + // only node for which this is true. + if (dir_vnid) + dirNode = btGetNodeFromVnid(dir_vnid); + else + dirNode = NULL; + + // If a node already exists with the given vnid, then it is either a symbolic + // link or an attempt to add the same node again, such as when mounting or + // walking a directory tree. If we find a matching vnid whose parent directory + // and name also match, this is a duplicate and can be ignored. + curNode = btGetNodeFromVnid(file_vnid); + if (curNode) + if (curNode->parent == dirNode && strcmp(curNode->name, name) == 0) + { + endWriting(&handleData); + return; + } + + // Allocate a new node. + curNode = (bt_node *) malloc(sizeof(bt_node)); + if (curNode == NULL) + { + endWriting(&handleData); + return; + } + + // Copy over the name, vnid, and parent node. Obtaining the parent + // node requires scanning the list. + strcpy(curNode->name, name); + curNode->refCount = 0; + curNode->invalid = false; + curNode->vnid = file_vnid; + curNode->parent = dirNode; + + // Add the node to the head of the list. + curNode->next = rootNode; + curNode->prev = NULL; + if (rootNode) + rootNode->prev = curNode; + rootNode = curNode; + + endWriting(&handleData); +} + +// btRemoveHandle() +// +void btRemoveHandle(vnode_id vnid) +{ + bt_node *deadNode; + + beginWriting(&handleData); + + // Obtain the node in question. If no such node exists, then we + // probably have a bad handle. + deadNode = btGetNodeFromVnid(vnid); + btRemoveNode(deadNode); + + endWriting(&handleData); +} + +// btRemoveNode() +// +void btRemoveNode(bt_node *deadNode) +{ + if (deadNode) + { + // If this node is the root node, then we need to reset the root node + // to the next node in the list. + if (deadNode == rootNode) + rootNode = deadNode->next; + + // Make this entry's predecessor point to its successor. + if (deadNode->prev) + deadNode->prev->next = deadNode->next; + + // Make this entry's successor point to its predecessor. + if (deadNode->next) + deadNode->next->prev = deadNode->prev; + + // Now deallocate this node. + free(deadNode); + } +} + +// btPurgeNodes() +// +void btPurgeNodes(vnode_id vnid) +{ + bt_node *curNode, *nextNode; + + beginWriting(&handleData); + + // First loop through, marking this node and all its children as invalid. + curNode = rootNode; + while (curNode) + { + if (curNode->vnid == vnid || btIsAncestorNode(vnid, curNode)) + curNode->invalid = true; + + curNode = curNode->next; + } + + // Now loop through again, removing all invalid nodes. This prevents removing + // a parent node and all its children being orphaned (with invalid pointers + // back to the destroyed parent). + curNode = rootNode; + while (curNode) + if (curNode->invalid) + { + nextNode = curNode->next; + btRemoveNode(curNode); + curNode = nextNode; + } + else + curNode = curNode->next; + + endWriting(&handleData); +} + +// btIsAncestorNode() +// +bool btIsAncestorNode(vnode_id vnid, bt_node *node) +{ + bt_node *curNode = node->parent; + + while (curNode) + { + if (curNode->vnid == vnid) + return true; + + curNode = curNode->parent; + } + + return false; +} + +// btGetLocalFileName() +// +char *btGetLocalFileName(char *path, vnode_id vnid) +{ + bt_node *node, *nodeStack[100]; + int stackSize; + + path[0] = 0; + stackSize = 1; + + beginReading(&handleData); + + node = btGetNodeFromVnid(vnid); + if (node == NULL) + { + endReading(&handleData); + return NULL; + } + + nodeStack[0] = node; + while ((node = node->parent) != NULL) + nodeStack[stackSize++] = node; + + while (--stackSize >= 0) + { + strcat(path, nodeStack[stackSize]->name); + if (stackSize) + strcat(path, "/"); + } + + endReading(&handleData); + return path; +} + +bt_node *btFindNode(bt_node *parent, char *fileName) +{ + bt_node *node; + + beginReading(&handleData); + + node = rootNode; + while (node) + { + if (node->parent == parent) + if (strcmp(node->name, fileName) == 0) + break; + + node = node->next; + } + + endReading(&handleData); + return node; +} + +char *btGetSharePath(char *shareName) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (strcasecmp(fileShares[i].name, shareName) == 0) + return fileShares[i].path; + + return NULL; +} + +int btGetShareId(char *shareName) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (strcasecmp(fileShares[i].name, shareName) == 0) + return i; + + return -1; +} + +int btGetShareIdByPath(char *path) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (strcmp(fileShares[i].path, path) == 0) + return i; + + return -1; +} + +// btGetRootPath() +// +void btGetRootPath(vnode_id vnid, char *path) +{ + bt_node *curNode; + + beginReading(&handleData); + + curNode = btGetNodeFromVnid(vnid); + while (curNode && curNode->parent) + curNode = curNode->parent; + + if (curNode) + strcpy(path, curNode->name); + else + path[0] = 0; + + endReading(&handleData); +} + +//////////////////////////////////////////////////////////////////// +/* +void btNotifyListeners(char *shareName) +{ + struct sockaddr_in toAddr, fromAddr; + int i; + + for (i = 0; i < BT_MAX_THREADS; i++) + if (strcasecmp(sessions[i].share, shareName) == 0) + { + memset(&toAddr, 0, sizeof(toAddr)); + toAddr.sin_port = htons(BT_NODE_MONITOR_PORT); + toAddr.sin_family = AF_INET; + toAddr.sin_addr.s_addr = sessions[i].s_addr; + + sendto(sock, packet, sizeof(packet), 0, &fromAddr, sizeof(fromAddr)); + } +} +*/ +//////////////////////////////////////////////////////////////////// + +int btPreMount(bt_session_t *session, char *shareName) +{ + // Look for the specified share name. If it can't be found, it must no longer be + // shared on this host. + int shareId = btGetShareId(shareName); + if (shareId < 0) + return ENOENT; + + return fileShares[shareId].security; +} + +int btMount(bt_session_t *session, char *shareName, char *user, char *password, vnode_id *vnid) +{ + bt_user_rights *ur; + struct stat st; + char *path, *groups[MAX_GROUPS_PER_USER]; + int i, shareId; + bool authenticated = false; + + // Initialize the groups array. We may need to release the memory later. + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + groups[i] = NULL; + + // Look for the specified share name. If it can't be found, it must no longer be + // shared on this host. + shareId = btGetShareId(shareName); + if (shareId < 0) + return ENOENT; + + if (fileShares[shareId].security != BT_AUTH_NONE) + { + // Authenticate the user with name/password + authenticated = authenticateUser(user, password); + if (!authenticated) + return EACCES; + + // Does the authenticated user have any rights on this file share? + session->rights = 0; + for (ur = fileShares[shareId].rights; ur; ur = ur->next) + if (!ur->isGroup && strcasecmp(ur->user, user) == 0) + session->rights |= ur->rights; + + // Does the authenticated user belong to any groups that have any rights on this + // file share? + getUserGroups(user, groups); + for (ur = fileShares[shareId].rights; ur; ur = ur->next) + if (ur->isGroup) + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + if (groups[i] && strcasecmp(ur->user, groups[i]) == 0) + { + session->rights |= ur->rights; + break; + } + + // Free the memory occupied by the group list. + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + if (groups[i]) + free(groups[i]); + + // If no rights have been granted, deny access. + if (session->rights == 0) + return EACCES; + + // If write access has been globally disabled, this user's rights must be + // correspondingly synchronized. + if (fileShares[shareId].readOnly) + session->rights = BT_RIGHTS_READ; + } + else + session->rights = fileShares[shareId].readOnly + ? BT_RIGHTS_READ + : BT_RIGHTS_READ | BT_RIGHTS_WRITE; + + // Make sure the folder we want to share still exists. + path = fileShares[shareId].path; + if (stat(path, &st) != 0) + return ENOENT; + + // Make sure it really is a folder and not a file. + if (!S_ISDIR(st.st_mode)) + return EACCES; + + *vnid = st.st_ino; + btAddHandle(0, *vnid, path); + return B_OK; +} + +int btGetFSInfo(char *rootPath, fs_info *fsInfo) +{ + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + if (fs_stat_dev(device, fsInfo) != 0) + return errno; + + return B_OK; +} + +int btLookup(char *pathBuf, vnode_id dir_vnid, char *fileName, vnode_id *file_vnid) +{ + bt_node *dnode, *fnode; + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + + *file_vnid = 0; + + beginReading(&handleData); + dnode = btGetNodeFromVnid(dir_vnid); + endReading(&handleData); + + if (!dnode) + return EACCES; + + // Search all nodes for one with the given parent vnid and file + // name. If one is found, we can simply use that node to fill in + // the new handle. + fnode = btFindNode(dnode, fileName); + if (fnode) + { + *file_vnid = fnode->vnid; + + folder = btGetLocalFileName(pathBuf, *file_vnid); + if (folder) + if (lstat(folder, &st) != 0) + { + btRemoveHandle(*file_vnid); + *file_vnid = 0; + return ENOENT; + } + } + else + { + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, fileName); + if (lstat(path, &st) != 0) + return ENOENT; + + *file_vnid = st.st_ino; + btAddHandle(dir_vnid, *file_vnid, fileName); + } + } + + return B_OK; +} + +int btStat(char *pathBuf, vnode_id vnid, struct stat *st) +{ + char *fileName; + int error; + + fileName = btGetLocalFileName(pathBuf, vnid); + if (fileName) + { + error = lstat(fileName, st); + return (error != 0 ? ENOENT : B_OK); + } + + return ENOENT; +} + +int btReadDir(char *pathBuf, vnode_id dir_vnid, DIR **dir, vnode_id *file_vnid, char *filename, struct stat *st) +{ + struct dirent *dirInfo; + char *folder, path[B_PATH_NAME_LENGTH]; + + if (dir_vnid == 0 || !file_vnid || !filename) + return EINVAL; + + if (!*dir) + { + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + *dir = opendir(folder); + } + + if (*dir) + { + if ((dirInfo = readdir(*dir)) != NULL) + { + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, dirInfo->d_name); + if (lstat(path, st) != 0) + return ENOENT; + + strcpy(filename, dirInfo->d_name); + *file_vnid = st->st_ino; + btAddHandle(dir_vnid, *file_vnid, filename); + return B_OK; + } + } + else + { + closedir(*dir); + return ENOENT; + } + } + + return EINVAL; +} + +int32 btRead(char *pathBuf, vnode_id vnid, off_t pos, int32 len, char *buffer) +{ + char *path; + int bytes; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + int file = open(path, O_RDONLY); + if (file < 0) + return errno; + + lseek(file, (int32) pos, SEEK_SET); + bytes = read(file, buffer, len); + close(file); + + // Return zero on any error. + if (bytes == -1) + bytes = 0; + + buffer[bytes] = 0; + return bytes; + } + + return 0; +} + +int32 btWrite(bt_session_t *session, vnode_id vnid, off_t pos, int32 len, int32 totalLen, char *buffer) +{ + bt_block *block; + + // If we've been given a total length, then we have a new buffered write + // session coming. A block will need to be allocated. + if (totalLen > 0) + { + // Make sure we don't have a wildly inaccurate total length to allocate. + if (totalLen > 10 * 1024 * 1024) + return 0; + + // Allocate a new buffered I/O block. + block = (bt_block *) malloc(sizeof(bt_block)); + if (block) + { + block->vnid = vnid; + block->pos = pos; + block->len = totalLen; + block->count = 0; + + block->buffer = (char *) malloc(totalLen + 1); + if (!block->buffer) + { + free(block); + return 0; + } + + btInsertWriteBlock(session, block); + } + else + return 0; + } + else + { + block = btGetWriteBlock(session, vnid); + if (!block) + return 0; + } + + memcpy(block->buffer + block->count, buffer, len); + block->count += len; + return len; +} + +// btGetWriteBlock() +// +bt_block *btGetWriteBlock(bt_session_t *session, vnode_id vnid) +{ + bt_block *block; + + btLock(session->blockSem, &session->blockVar); + + block = session->rootBlock; + while (block && block->vnid != vnid) + block = block->next; + + btUnlock(session->blockSem, &session->blockVar); + return block; +} + +// btInsertWriteBlock() +// +void btInsertWriteBlock(bt_session_t *session, bt_block *block) +{ + btLock(session->blockSem, &session->blockVar); + + block->next = session->rootBlock; + block->prev = NULL; + if (session->rootBlock) + session->rootBlock->prev = block; + + session->rootBlock = block; + + btUnlock(session->blockSem, &session->blockVar); +} + +int btCommit(bt_session_t *session, vnode_id vnid) +{ + bt_block *block; + char *path; + int file; + + // Get the full path for the specified file. + path = btGetLocalFileName(session->pathBuffer, vnid); + if (!path) + return ENOENT; + + // Obtain the buffered I/O block. If one can't be found, no buffered I/O + // session was started for this vnode. + block = btGetWriteBlock(session, vnid); + if (!block) + return ENOENT; + + // Open the file for writing. + file = open(path, O_WRONLY | O_CREAT); + if (file < 0) + return errno; + + btLock(session->blockSem, &session->blockVar); + + // Write the data. + lseek(file, (int32) block->pos, SEEK_SET); + write(file, block->buffer, block->len); + + btRemoveWriteBlock(session, block); + btUnlock(session->blockSem, &session->blockVar); + + close(file); + return B_OK; +} + +void btRemoveWriteBlock(bt_session_t *session, bt_block *block) +{ + // If we're removing the root, then adjust the root block pointer. + if (session->rootBlock == block) + session->rootBlock = block->next; + + // If there's a previous block, it should now point beyond this block. + if (block->prev) + block->prev->next = block->next; + + // If there's a next block, it should now point to the current predecessor. + if (block->next) + block->next->prev = block->prev; + + // Release the memory used by this block. + free(block->buffer); + free(block); +} + +int btCreate(char *pathBuf, vnode_id dir_vnid, char *name, int omode, int perms, vnode_id *file_vnid) +{ + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + int fh; + + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + fh = open(path, O_WRONLY | O_CREAT | O_TRUNC | omode, perms); + if (fh == -1) + return errno; + else + { + close(fh); + if (lstat(path, &st) == 0) + { + *file_vnid = st.st_ino; + btAddHandle(dir_vnid, *file_vnid, name); + } + else + return EACCES; + } + } + + return B_OK; +} + +int btTruncate(char *pathBuf, vnode_id vnid, int64 len) +{ + char *path; + int error; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + error = truncate(path, len); + if (error == -1) + return errno; + + return B_OK; + } + + return EACCES; +} + +// btCreateDir() +// +int btCreateDir(char *pathBuf, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, struct stat *st) +{ + char path[B_PATH_NAME_LENGTH], *folder; + + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + if (mkdir(path, perms) != B_OK) + return EACCES; + + if (lstat(path, st) != 0) + return errno; + + *file_vnid = st->st_ino; + btAddHandle(dir_vnid, *file_vnid, name); + return B_OK; + } + + return ENOENT; +} + +// btDeleteDir() +// +int btDeleteDir(char *pathBuf, vnode_id vnid, char *name) +{ + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + + folder = btGetLocalFileName(pathBuf, vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + if (lstat(path, &st) != 0) + return errno; + + if (rmdir(path) == -1) + return errno; + + btPurgeNodes(st.st_ino); + return B_OK; + } + + return ENOENT; +} + +// btRename() +// +int btRename(char *pathBuf, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName) +{ + struct stat st; + char oldPath[B_PATH_NAME_LENGTH], newPath[B_PATH_NAME_LENGTH], *oldFolder, *newFolder; + + oldFolder = btGetLocalFileName(pathBuf, old_vnid); + if (oldFolder) + { + sprintf(oldPath, "%s/%s", oldFolder, oldName); + + newFolder = btGetLocalFileName(pathBuf, new_vnid); + if (newFolder) + { + sprintf(newPath, "%s/%s", newFolder, newName); + + if (lstat(oldPath, &st) != 0) + return errno; + + btPurgeNodes(st.st_ino); + + if (rename(oldPath, newPath) == -1) + return errno; + + return B_OK; + } + } + + return ENOENT; +} + +// btUnlink() +// +int btUnlink(char *pathBuf, vnode_id vnid, char *name) +{ + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + int error; + + folder = btGetLocalFileName(pathBuf, vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + + // Obtain the inode (vnid) of the specified file through lstat(). + if (lstat(path, &st) != 0) + return errno; + + // Construct a dummy file descriptor and cause it to be removed from + // the list. + btRemoveHandle(st.st_ino); + + error = unlink(path); + return (error == -1 ? errno : B_OK); + } + + return EACCES; +} + +int btReadLink(char *pathBuf, vnode_id vnid, char *buffer, int length) +{ + char *path; + int error; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + error = readlink(path, buffer, length); + if (error == -1) + return errno; + + // If readlink() didn't return -1, it returned the number of bytes supplied in the + // buffer. It seems, however, that it does not null-terminate the string for us. + buffer[error] = 0; + return B_OK; + } + + return ENOENT; +} + +int btSymLink(char *pathBuf, vnode_id vnid, char *name, char *dest) +{ + char path[B_PATH_NAME_LENGTH], *folder; + + folder = btGetLocalFileName(pathBuf, vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + if (symlink(dest, path) == -1) + return errno; + + return B_OK; + } + + return ENOENT; +} + +int btWStat(char *pathBuf, vnode_id vnid, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime) +{ + struct utimbuf ftimes; + struct stat st; + char *path; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + if (mask & WSTAT_MODE) + chmod(path, mode); + + // BeOS doesn't support passing -1 as the user ID or group ID, which normally would + // simply leave the value unchanged. This complicates things a bit, but keep in + // mind that BeOS doesn't really support multiple users anyway. + if (mask & WSTAT_UID && mask & WSTAT_GID) + chown(path, uid, gid); + +// if (mask & WSTAT_UID) +// chown(path, uid, -1); + +// if (mask & WSTAT_GID) +// chown(path, -1, gid); + + if (mask & WSTAT_SIZE) + truncate(path, size); + + if (lstat(path, &st) == 0) + if (mask & WSTAT_ATIME || mask & WSTAT_MTIME) + { + ftimes.actime = mask & WSTAT_ATIME ? atime : st.st_atime; + ftimes.modtime = mask & WSTAT_MTIME ? mtime : st.st_mtime; + utime(path, &ftimes); + } + + return B_OK; + } + + return ENOENT; +} + +int btReadAttrib(char *pathBuf, vnode_id vnid, char *name, int32 dataType, void *buffer, int32 pos, int32 len) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int bytes = (int) fs_read_attr(file, name, dataType, pos, buffer, len); + close(file); + + if ((dataType == B_STRING_TYPE || dataType == B_MIME_TYPE) && bytes < len && bytes >= 0) + ((char *) buffer)[bytes] = 0; + + return bytes; + } + } + + return ENOENT; +} + +int btWriteAttrib(char *pathBuf, vnode_id vnid, char *name, int32 dataType, void *buffer, int32 pos, int32 len) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int bytes = (int) fs_write_attr(file, name, dataType, pos, buffer, len); + close(file); + return bytes; + } + } + + return ENOENT; +} + +int btReadAttribDir(char *pathBuf, vnode_id vnid, DIR **dir, char *attrName) +{ + dirent_t *entry; + char *path; + + if (!attrName) + return EINVAL; + + if (!*dir) + { + path = btGetLocalFileName(pathBuf, vnid); + if (path) + *dir = fs_open_attr_dir(path); + } + + if (*dir) + do + { + entry = fs_read_attr_dir(*dir); + if (entry) + { + if (strncmp(entry->d_name, "_trk/", 5) == 0) + continue; + + strcpy(attrName, entry->d_name); + return B_OK; + } + } while (entry); + + if (*dir) + fs_close_attr_dir(*dir); + + return ENOENT; +} + +int btRemoveAttrib(char *pathBuf, vnode_id vnid, char *name) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int error = fs_remove_attr(file, name); + if (error == -1) + error = errno; + + close(file); + return error; + } + } + + return ENOENT; +} + +int btStatAttrib(char *pathBuf, vnode_id vnid, char *name, struct attr_info *info) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int error = fs_stat_attr(file, name, info); + if (error == -1) + error = errno; + + close(file); + return error; + } + } + + return ENOENT; +} + +int btReadIndexDir(char *rootPath, DIR **dir, char *indexName) +{ + struct dirent *dirInfo; + + if (!*dir) + { + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + *dir = fs_open_index_dir(device); + } + + if (*dir) + if ((dirInfo = fs_read_index_dir(*dir)) != NULL) + { + strcpy(indexName, dirInfo->d_name); + return B_OK; + } + else + { + fs_close_index_dir(*dir); + *dir = NULL; + return ENOENT; + } + + return ENOENT; +} + +int btCreateIndex(char *rootPath, char *name, int type, int flags) +{ + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + if (fs_create_index(device, name, type, flags) == -1) + return errno; + + return B_OK; +} + +int btRemoveIndex(char *rootPath, char *name) +{ + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + if (fs_remove_index(device, name) == -1) + return errno; + + return B_OK; +} + +int btStatIndex(char *rootPath, char *name, struct index_info *info) +{ + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + if (fs_stat_index(device, name, info) == -1) + return errno; + + return B_OK; +} + +int btReadQuery(char *rootPath, DIR **dir, char *query, char *fileName, vnode_id *vnid, vnode_id *parent) +{ + struct dirent *dirInfo; + + if (!*dir) + { + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + *dir = fs_open_query(device, query, 0); + } + + if (*dir) + if ((dirInfo = fs_read_query(*dir)) != NULL) + { + *vnid = dirInfo->d_ino; + *parent = dirInfo->d_pino; + strcpy(fileName, dirInfo->d_name); + return B_OK; + } + else + { + fs_close_query(*dir); + *dir = NULL; + return ENOENT; + } + + return ENOENT; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_workers.h b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_workers.h new file mode 100644 index 0000000000..0975fcd27f --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/rpc_workers.h @@ -0,0 +1,67 @@ +#ifndef _RPC_WORKERS_ +#define _RPC_WORKERS_ + +#include "betalk.h" +#include "sessions.h" + +typedef struct btnode +{ + vnode_id vnid; + char name[B_FILE_NAME_LENGTH]; + int refCount; + bool invalid; + struct btnode *next; + struct btnode *prev; + struct btnode *parent; +} bt_node; + + +int btPreMount(bt_session_t *session, char *shareName); +int btMount(bt_session_t *session, char *shareName, char *user, char *password, vnode_id *vnid); +int btGetFSInfo(char *rootPath, fs_info *fsInfo); +int btLookup(char *pathBuf, vnode_id dir_vnid, char *fileName, vnode_id *file_vnid); +int btStat(char *pathBuf, vnode_id vnid, struct stat *st); +int btReadDir(char *pathBuf, vnode_id dir_vnid, DIR **dir, vnode_id *file_vnid, char *filename, struct stat *st); +int32 btRead(char *pathBuf, vnode_id vnid, off_t pos, int32 len, char *buffer); +int32 btWrite(bt_session_t *session, vnode_id vnid, off_t pos, int32 len, int32 totalLen, char *buffer); +int btCreate(char *pathBuf, vnode_id dir_vnid, char *name, int omode, int perms, vnode_id *file_vnid); +int btTruncate(char *pathBuf, vnode_id vnid, int64 len); +int btCreateDir(char *pathBuf, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, struct stat *st); +int btDeleteDir(char *pathBuf, vnode_id vnid, char *name); +int btRename(char *pathBuf, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName); +int btUnlink(char *pathBuf, vnode_id vnid, char *name); +int btReadLink(char *pathBuf, vnode_id vnid, char *buffer, int length); +int btSymLink(char *pathBuf, vnode_id vnid, char *name, char *dest); +int btWStat(char *pathBuf, vnode_id vnid, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime); +int btReadAttrib(char *pathBuf, vnode_id vnid, char *name, int32 dataType, void *buffer, int32 pos, int32 len); +int btWriteAttrib(char *pathBuf, vnode_id vnid, char *name, int32 dataType, void *buffer, int32 pos, int32 len); +int btReadAttribDir(char *pathBuf, vnode_id vnid, DIR **dir, char *attrName); +int btRemoveAttrib(char *pathBuf, vnode_id vnid, char *name); +int btStatAttrib(char *pathBuf, vnode_id vnid, char *name, struct attr_info *info); +int btReadIndexDir(char *rootPath, DIR **dir, char *indexName); +int btCreateIndex(char *rootPath, char *name, int type, int flags); +int btRemoveIndex(char *rootPath, char *name); +int btStatIndex(char *rootPath, char *name, struct index_info *info); +int btReadQuery(char *rootPath, DIR **dir, char *query, char *fileName, vnode_id *vnid, vnode_id *parent); +int btCommit(bt_session_t *session, vnode_id vnid); + +bt_block *btGetWriteBlock(bt_session_t *session, vnode_id vnid); +void btInsertWriteBlock(bt_session_t *session, bt_block *block); +void btRemoveWriteBlock(bt_session_t *session, bt_block *block); + +bt_node *btGetNodeFromVnid(vnode_id vnid); +void btAddHandle(vnode_id dir_vnid, vnode_id file_vnid, char *name); +void btRemoveHandle(vnode_id vnid); +void btPurgeNodes(vnode_id vnid); +void btRemoveNode(bt_node *deadNode); +bool btIsAncestorNode(vnode_id vnid, bt_node *node); +char *btGetLocalFileName(char *path, vnode_id vnid); +bt_node *btFindNode(bt_node *parent, char *fileName); +char *btGetSharePath(char *shareName); +int btGetShareId(char *shareName); +int btGetShareIdByPath(char *path); +void btGetRootPath(vnode_id vnid, char *path); +void btLock(sem_id semaphore, int32 *atomic); +void btUnlock(sem_id semaphore, int32 *atomic); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/sessions.h b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/sessions.h new file mode 100644 index 0000000000..7d9ee9bbb5 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/sessions.h @@ -0,0 +1,50 @@ +#ifndef _SESSIONS_H_ +#define _SESSIONS_H_ + +#include "betalk.h" +#include "fsproto.h" + +typedef struct +{ + unsigned int type; + unsigned int length; + char *data; +} bt_arg_t; + +typedef struct btblock +{ + vnode_id vnid; + off_t pos; + int32 len; + int32 count; + char *buffer; + struct btblock *next; + struct btblock *prev; +} bt_block; + +typedef struct session +{ + int socket; + unsigned int client_s_addr; + thread_id handlerID; + + bool killed; + + // What share did the client connect to? And when? + int share; + int rights; + time_t logon; + + // Buffered write support. + bt_block *rootBlock; + sem_id blockSem; + int32 blockVar; + + char ioBuffer[BT_MAX_IO_BUFFER + 9]; + char attrBuffer[BT_MAX_ATTR_BUFFER + 1]; + char pathBuffer[B_PATH_NAME_LENGTH + 1]; + + struct session *next; +} bt_session_t; + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/sysdepdefs.h b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/sysdepdefs.h new file mode 100644 index 0000000000..6bb4bd5051 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-1.2.6/sysdepdefs.h @@ -0,0 +1,10 @@ +#ifndef _SYSDEPDEFS_H_ +#define _SYSDEPDEFS_H_ + +#ifdef BONE_VERSION + +#define closesocket(s) close(s) + +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BeServed-MimeMap b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BeServed-MimeMap new file mode 100644 index 0000000000..6bba642475 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BeServed-MimeMap @@ -0,0 +1,116 @@ +class application/java +hqx application/mac-binhex40 +doc application/msword +dot application/msword +bin application/octet-stream +dump application/octet-stream +exe application/octet-stream +o application/octet-stream +pdf application/pdf +ai application/postscript +eps application/postscript +ps application/postscript +smi application/smil +smil application/smil +xls application/vnd.ms-excel +ppt application/vnd.ms-powerpoint +rm application/vnd.rn-realmedia +rn application/vnd.rn-realplayer +rsrc application/x-be-resource +bz2 application/x-bzip2 +dvi application/x-dvi +gtar application/x-gtar +gz application/x-gzip +tgz application/x-gzip +Z application/x-gzip +js application/x-javascript +proj application/x-mw-project +pkg application/x-scode-UPkg +vdwn application/x-scode-VDwn +swf application/x-shockwave-flash +tar application/x-tar +tcl application/x-tcl +man application/x-troff-man +so application/x-vnd.Be-elfexecutable +metos application/x-vnd.CKJ-MeTOS-Project +zip application/zip +au audio/basic +snd audio/basic +mid audio/midi +midi audio/midi +kar audio/midi +mpga audio/mpeg +mp2 audio/x-mpeg +mp3 audio/x-mpeg +aif audio/aiff +aiff audio/aiff +riff audio/riff +aifc audio/x-aifc +ram audio/x-pn-realaudio +rm audio/x-pn-realaudio +rpm audio/x-pn-realaudio-plugin +ra audio/vnd.rn-realaudio +wav audio/wav +bmp image/bmp +gif image/gif +jpeg image/jpeg +jpg image/jpeg +jpe image/jpeg +png image/png +tiff image/tiff +tif image/tiff +rf image/vnd.rn-realflash +rp image/vnd.rn-realpix +psd image/x-photoshop +ppm image/x-portable-pixmap +IDF image/x-refraction-document +idf image/x-refraction-document +tga image/x-targa +wrl model/vrml +vrml model/vrml +asp text/asp +css text/css +htm text/html +html text/html +shtml text/html +p text/pascal +pas text/pascal +asc text/plain +conf text/plain +f text/plain +f77 text/plain +f90 text/plain +for text/plain +jav text/plain +java text/plain +log text/plain +lst text/plain +php text/plain +sh text/plain +txt text/plain +rtf text/rtf +sgml text/sgml +sgm text/sgml +tsv text/tab-separated-values +rt text/vnd.rn-realtext +asm text/x-asm +s text/x-asm +c text/x-source-code +cc text/x-source-code +cpp text/x-source-code +h text/x-source-code +h++ text/x-source-code +pl text/x-source-code +py text/x-source-code +rdef text/x-vnd.Be.ResourceDef +xml text/xml +mpeg video/mpeg +mpg video/mpeg +mpe video/mpeg +qt video/quicktime +mov video/quicktime +rv video/vnd.rn-realvideo +viv video/vnd.vivo +vivo video/vnd.vivo +avi video/x-msvideo +movie video/x-sgi-movie diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BeServed-Settings b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BeServed-Settings new file mode 100644 index 0000000000..ac0634fa30 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BeServed-Settings @@ -0,0 +1,17 @@ +# If BeSure authentication is desired, the command below can be used +# to specify the network name or address of the server. +# authenticate with 10.1.6.15 + +# Define a shared folder "c:\temp" that will be called "Temp Folder" +# and will have read-write access. +share c:\temp as "Temp Folder" +set "Temp Folder" read-write + +# If BeSure authentication is configured, specific rights can be granted +# to users and/or groups using the grant command, as illustrated below. +#grant read on "Temp Folder" to everyone + +# Shared printers can be configured using the printer command. Various +# details need to be supplied regarding the printer and a location to +# temporarily spool print jobs being submitted by other users. +# printer "Okidata OL-1200" is type PCL3 device "Okidata OL-1200" spooled to c:\temp \ No newline at end of file diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BeServed.cpp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BeServed.cpp new file mode 100644 index 0000000000..77af4607fb --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BeServed.cpp @@ -0,0 +1,3581 @@ +// BeServed.cpp : Defines the entry point for the application. +// + +#include "stdafx.h" + +#include "beCompat.h" +#include "betalk.h" +#include "authentication.h" +#include "readerWriter.h" +#include "printing.h" +#include "ubi_SplayTree.h" + +// Windows service-specific header files. +#include "winsvc.h" +#include "NTServApp.h" +#include "myservice.h" + +#define BT_MAX_THREADS 100 +#define BT_MAX_RETRIES 3 +#define BT_MAX_FILE_SHARES 128 +#define BT_MAX_PRINTER_SHARES 16 + +#define BT_THREAD_NAME "BeServed Handler" +#define BT_HOST_THREAD_NAME "BeServed Host Publisher" + +#define PATH_ROOT "/boot" +#define PATH_DELIMITER '/' + +#ifndef iswhite +#define iswhite(c) ((c == ' ' || c == '\t')) +#endif + +typedef struct +{ + unsigned int type; + unsigned int length; + char *data; +} bt_arg_t; + +typedef struct btblock +{ + vnode_id vnid; + beos_off_t pos; + int32 len; + int32 count; + char *buffer; + struct btblock *next; + struct btblock *prev; +} bt_block; + +typedef struct session +{ + int socket; + unsigned int client_s_addr; + HANDLE handlerID; + + bool killed; + + // The user that is connected. + char user[MAX_NAME_LENGTH + 1]; + + // What share did the client connect to? And when? + int share; + int rights; + time_t logon; + + // Buffered write support. + bt_block *rootBlock; + sem_id blockSem; + + char ioBuffer[BT_MAX_IO_BUFFER + 1]; + char attrBuffer[BT_MAX_ATTR_BUFFER + 1]; + char pathBuffer[B_PATH_NAME_LENGTH]; + + struct session *next; +} bt_session_t; + +typedef void (*bt_net_func)(bt_session_t *, unsigned int, int, bt_arg_t *); + +typedef struct dirCommand +{ + unsigned char command; + bt_net_func handler; + bool supported; + uint8 args; + uint32 argTypes[MAX_COMMAND_ARGS]; +} bt_command_t; + +typedef struct +{ + vnode_id vnid; + int shareId; + char unused[20]; +} bt_fdesc; + +typedef struct btnode +{ + ubi_trNode node; + vnode_id vnid; + char *name; + bool invalid; + struct btnode *parent; +} bt_node; + +typedef struct fileShare +{ + char path[B_PATH_NAME_LENGTH]; + char name[B_FILE_NAME_LENGTH]; + + bool used; + bool readOnly; + + // What rights does each user have? + bt_user_rights *rights; + int security; + + struct fileShare *next; +} bt_fileShare_t; + +typedef struct mime_mapping +{ + char extension[7]; + char *mimeType; + struct mime_mapping *next; +} bt_mime_mapping; + + +void BeServedStartup(CMyService *service); +bool dateCheck(); +DWORD WINAPI btSendHost(LPVOID data); +void getHostInfo(bt_hostinfo *info); +int getSharedResources(char *buffer, int bufSize, bool shares, bool printers); +int getHostUsers(char *buffer); +void startService(); +void endService(int sig); +void initMimeMap(); +void closeMimeMap(); +void closePrinters(); +void freeFileShares(); +void waitForThread(HANDLE threadId); + +void initShares(); +void initPrinters(); +void loadShares(); +void getFileShare(const char *buffer); +void loadFolder(const char *path); +void getShareProperty(const char *buffer); +void getAuthenticate(const char *buffer); +bool getAuthServerAddress(const char *name); +void addUserRights(char *share, char *user, int rights, bool isGroup); +void getGrant(const char *buffer); +void getPrinter(const char *buffer); +int getToken(); + +int receiveRequest(bt_session_t *session); +void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]); +void launchThread(int client, struct sockaddr_in *addr); +int tooManyConnections(unsigned int _s_addr); +void sendErrorToClient(int client, unsigned int xid, int error); +void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command); +DWORD WINAPI requestThread(LPVOID data); +DWORD WINAPI printerThread(LPVOID data); + +void KillNode(ubi_trNodePtr node); +int CompareVnidNodes(ubi_trItemPtr item, ubi_trNodePtr node); +int CompareNameNodes(ubi_trItemPtr item, ubi_trNodePtr node); + +bt_node *btGetNodeFromVnid(vnode_id vnid); +void btAddHandle(vnode_id dir_vnid, vnode_id file_vnid, char *name); +void btRemoveHandle(vnode_id vnid); +void btPurgeNodes(vnode_id vnid); +bool btIsAncestorNode(vnode_id vnid, bt_node *node); +char *btGetLocalFileName(char *path, vnode_id vnid); +void btMakeHandleFromNode(bt_node *node, vnode_id vnid); +bt_node *btFindNode(bt_node *parent, char *fileName); +char *btGetSharePath(char *shareName); +int btGetShareId(char *shareName); +int btGetShareIdByPath(char *path); +bt_printer *btFindPrinter(char *printerName); +uint32 btGetWinInode(const char *path); +int btGetBeosStat(char *fileName, beos_stat *st); +void btMakePath(char *path, char *dir, char *file); + +int btPreMount(bt_session_t *session, char *shareName); +int btMount(bt_session_t *session, char *shareName, char *user, char *password, vnode_id *vnid); +int btGetFSInfo(fs_info *fsInfo, char *path); +int btLookup(char *pathBuf, vnode_id dir_vnid, char *fileName, vnode_id *file_vnid); +int btStat(char *pathBuf, vnode_id vnid, beos_stat *st); +int btReadDir(char *pathBuf, vnode_id dir_vnid, long **dir, vnode_id *file_vnid, char *filename, beos_stat *st); +int32 btRead(char *pathBuf, vnode_id vnid, beos_off_t pos, int32 len, char *buffer); +int32 btWrite(bt_session_t *session, vnode_id vnid, beos_off_t pos, int32 len, int32 totalLen, char *buffer); +int btCreate(char *pathBuf, vnode_id dir_vnid, char *name, int omode, int perms, vnode_id *file_vnid); +int btTruncate(char *pathBuf, vnode_id vnid, int64 len); +int btCreateDir(char *pathBuf, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, beos_stat *st); +int btDeleteDir(char *pathBuf, vnode_id dir_vnid, char *name); +int btRename(char *pathBuf, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName); +int btUnlink(char *pathBuf, vnode_id vnid, char *name); +int btReadLink(char *pathBuf, vnode_id vnid, char *buffer, int length); +int btSymLink(char *pathBuf, vnode_id vnid, char *name, char *dest); +int btWStat(char *pathBuf, vnode_id vnid, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime); +int btCommit(bt_session_t *session, vnode_id vnid); +int btReadAttrib(char *pathBuf, vnode_id vnid, char *name, char *buffer); +int btAuthenticate(char *resource, char *user, char *password); + +bt_block *btGetWriteBlock(bt_session_t *session, vnode_id vnid); +void btInsertWriteBlock(bt_session_t *session, bt_block *block); +void btRemoveWriteBlock(bt_session_t *session, bt_block *block); + +void netbtPreMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtPrintJobNew(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtPrintJobData(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtPrintJobCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); + +CMyService *winService; +bt_node *rootNode = NULL; +ubi_btRoot vnidTree; +ubi_btRoot nameTree; +bt_mime_mapping *mimeMap = NULL; +bt_session_t *rootSession = NULL; +bt_fileShare_t fileShares[BT_MAX_FILE_SHARES]; +bt_printer sharedPrinters[BT_MAX_PRINTER_SHARES]; +char tokBuffer[MAX_NAME_LENGTH + 1], *tokPtr; +bool running = true; +bool preload = false; +int server; +char authServerName[B_FILE_NAME_LENGTH]; +unsigned int authServerIP; +bt_managed_data handleData; +bt_managed_data sessionData; +HANDLE hostThread; + +char *keywords[] = +{ + "share", + "as", + "set", + "read", + "write", + "read-write", + "promiscuous", + "on", + "to", + "authenticate", + "with", + "group", + "printer", + "print", + "is", + "spooled", + "device", + "type", + "preload", + NULL +}; + +bt_command_t dirCommands[] = +{ + { BT_CMD_PREMOUNT, netbtPreMount, true, 1, { B_STRING_TYPE } }, + { BT_CMD_MOUNT, netbtMount, true, 3, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_FSINFO, netbtFSInfo, true, 1, { B_INT64_TYPE } }, + { BT_CMD_LOOKUP, netbtLookup, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_STAT, netbtStat, true, 1, { B_INT64_TYPE } }, + { BT_CMD_READDIR, netbtReadDir, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_READ, netbtRead, true, 3, { B_INT64_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_WRITE, netbtWrite, true, 5, { B_INT64_TYPE, B_INT64_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_STRING_TYPE } }, + { BT_CMD_CREATE, netbtCreate, true, 4, { B_INT64_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_TRUNCATE, netbtTruncate, true, 2, { B_INT64_TYPE, B_INT64_TYPE } }, + { BT_CMD_MKDIR, netbtCreateDir, true, 3, { B_INT64_TYPE, B_STRING_TYPE, B_INT32_TYPE } }, + { BT_CMD_RMDIR, netbtDeleteDir, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_RENAME, netbtRename, true, 4, { B_INT64_TYPE, B_STRING_TYPE, B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_UNLINK, netbtUnlink, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, + { BT_CMD_READLINK, netbtReadLink, false, 1, { B_INT64_TYPE } }, + { BT_CMD_SYMLINK, netbtSymLink, false, 3, { B_INT64_TYPE, B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_WSTAT, netbtWStat, true, 8, { B_INT64_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_READATTRIB, netbtReadAttrib, true, 5, { B_STRING_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_WRITEATTRIB, netbtWriteAttrib, false, 6, { B_STRING_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_READATTRIBDIR, netbtReadAttribDir, false, 2, { B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_REMOVEATTRIB, netbtRemoveAttrib, false, 2, { B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_STATATTRIB, netbtStatAttrib, true, 2, { B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_READINDEXDIR, netbtReadIndexDir, false, 1, { B_STRING_TYPE } }, + { BT_CMD_CREATEINDEX, netbtCreateIndex, false, 3, { B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, + { BT_CMD_REMOVEINDEX, netbtRemoveIndex, false, 1, { B_STRING_TYPE } }, + { BT_CMD_STATINDEX, netbtStatIndex, false, 1, { B_STRING_TYPE } }, + { BT_CMD_READQUERY, netbtReadQuery, false, 2, { B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_COMMIT, netbtCommit, true, 1, { B_INT64_TYPE } }, + { BT_CMD_PRINTJOB_NEW, netbtPrintJobNew, true, 4, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_PRINTJOB_DATA, netbtPrintJobData, true, 4, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE, B_INT32_TYPE } }, + { BT_CMD_PRINTJOB_COMMIT, netbtPrintJobCommit, true, 2, { B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_AUTHENTICATE, netbtAuthenticate, true, 3, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE } }, + { BT_CMD_QUIT, netbtQuit, true, 0, { 0 } }, + { 0, NULL, false, 0, { 0 } } +}; + + +//int APIENTRY WinMain(HINSTANCE hInstance, +// HINSTANCE hPrevInstance, +// LPSTR lpCmdLine, +// int nCmdShow) +void BeServedStartup(CMyService *service) +{ + WSADATA wsaData; + DWORD threadId; + + ASSERT(service); + winService = service; + + initPrinters(); + + initMimeMap(); + initShares(); + signal(SIGINT, endService); + signal(SIGTERM, endService); + + // Initialize the trees sorted by vnode_id and by name. + ubi_trInitTree(&vnidTree, CompareVnidNodes, 0); + ubi_trInitTree(&nameTree, CompareNameNodes, 0); + + if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) + return; + + if (initManagedData(&handleData)) + if (initManagedData(&sessionData)) + hostThread = CreateThread(NULL, 0, btSendHost, NULL, 0, &threadId); +} + +bool dateCheck() +{ + struct _stat st; + time_t curTime; + + time(&curTime); + if (curTime > 1012537700) + return false; + + if (_stat("/boot/home/config/servers/beserved_server", &st) == 0) + if (curTime < st.st_ctime || curTime > st.st_ctime + 7776000) + return false; + + return true; +} + +void restartService() +{ + bt_fileShare_t *oldShares; + int i; + + // Printers are easier because the printer name is sent with each print request. + // If the printer is no longer available, the next transmission sent regarding + // that printer will result in an error, terminating the print job on the client. + // All we have to do is clear out the structures, and initShares will read the + // configuration file. + initPrinters(); + + // Delay all mounting and other file system operations. + beginWriting(&handleData); + beginWriting(&sessionData); + + // Copy existing share data. + oldShares = (bt_fileShare_t *) malloc(sizeof(bt_fileShare_t) * BT_MAX_FILE_SHARES); + if (oldShares) + { + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + memcpy(&oldShares[i], &fileShares[i], sizeof(bt_fileShare_t)); + + // Reload the share data. + initShares(); + + // Now loop through the old file shares. For each one, check if the same + // path exists in the new shares. + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (oldShares[i].used) + { + bt_session_t *s; + int share = btGetShareIdByPath(oldShares[i].path); + if (share == -1) + { + for (s = rootSession; s; s = s->next) + if (s->share == i) + s->killed = true; + } + else if (share != i) + { + for (s = rootSession; s; s = s->next) + if (s->share == i) + s->share = share; + } + } + + free(oldShares); + } + + // Resume normal operation. + endWriting(&sessionData); + endWriting(&handleData); +} + +DWORD WINAPI btSendHost(LPVOID data) +{ + bt_request request; + bt_hostinfo info; + struct sockaddr_in serverAddr, clientAddr; + char buffer[4096]; + int server, addrLen, bufLen, replyLen; + + buffer[0] = 0; + bufLen = sizeof(buffer); + + server = socket(AF_INET, SOCK_DGRAM, 0); + if (server == INVALID_SOCKET) + return 0; + + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(BT_QUERYHOST_PORT); + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Bind that socket to the address constructed above. + if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return 0; + + while (running) + { + addrLen = sizeof(struct sockaddr_in); + replyLen = 0; + if (recvfrom(server, (char *) &request, sizeof(request), 0, (struct sockaddr *) &clientAddr, &addrLen) <= 0) + continue; + + switch (request.command) + { + case BT_REQ_HOST_PROBE: + gethostname(buffer, bufLen); + break; + + case BT_REQ_SHARE_PROBE: + replyLen = getSharedResources(buffer, sizeof(buffer), true, true); + break; + + case BT_REQ_PRINTER_PROBE: + replyLen = getSharedResources(buffer, sizeof(buffer), false, true); + break; + + case BT_REQ_HOST_INFO: + getHostInfo(&info); + memcpy(buffer, &info, sizeof(bt_hostinfo)); + replyLen = sizeof(bt_hostinfo); + break; + + case BT_REQ_HOST_USERS: + replyLen = getHostUsers(buffer); + break; + } + + // If no reply length has been specified, calculate it now by taking the + // length of the buffer. + if (replyLen == 0) + replyLen = strlen(buffer); + + sendto(server, buffer, replyLen, 0, (struct sockaddr *) &clientAddr, addrLen); + } + + // Close the socket. Technically, I believe we should call shutdown() + // first, but the BeOS header file socket.h indicates that this + // function is not currently working. It is present but may not have + // any effect. + shutdown(server, 2); + closesocket(server); + return 0; +} + +// getSharedResources() +// +int getSharedResources(char *buffer, int bufSize, bool shares, bool printers) +{ + bt_resource resource; + int i, bufPos = 0; + + // If the supplied buffer can't hold at least two resource structures, one + // for a shared resource and one to terminate the list, then don't bother + // building the list. + if (bufSize < 2 * sizeof(bt_resource)) + return 0; + + if (shares) + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + { + // If this is the last resource structure that will fit in the + // buffer, then don't add any more into the list. + if (bufPos + sizeof(bt_resource) >= bufSize) + break; + + // Fill out the resource structure. + resource.type = BT_SHARED_FOLDER; + resource.subType = 0; + strcpy(resource.name, fileShares[i].name); + + // Copy the resource structure into the buffer at the current offset. + memcpy(buffer + bufPos, &resource, sizeof(bt_resource)); + bufPos += sizeof(bt_resource); + } + + if (printers) + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + if (sharedPrinters[i].used) + { + // If this is the last resource structure that will fit in the + // buffer, then don't add any more into the list. + if (bufPos + sizeof(bt_resource) >= bufSize) + break; + + // Fill out the resource structure. + resource.type = BT_SHARED_PRINTER; + resource.subType = BT_PRINTER_PCL3; + strcpy(resource.name, sharedPrinters[i].printerName); + + // Copy the resource structure into the buffer at the current offset. + memcpy(buffer + bufPos, &resource, sizeof(bt_resource)); + bufPos += sizeof(bt_resource); + } + + // Copy the null terminating structure. + resource.type = BT_SHARED_NULL; + resource.subType = 0; + resource.name[0] = 0; + memcpy(buffer + bufPos, &resource, sizeof(bt_resource)); + bufPos += sizeof(bt_resource); + + return bufPos; +} + +// getHostInfo() +// +void getHostInfo(bt_hostinfo *info) +{ + SYSTEM_INFO systemInfo; + OSVERSIONINFOEX osInfo; + bt_session_t *s; + + osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if (!GetVersionEx((OSVERSIONINFO *) &osInfo)) + { + osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx((OSVERSIONINFO *) &osInfo); + } + + GetSystemInfo(&systemInfo); + + switch (osInfo.dwPlatformId) + { + case VER_PLATFORM_WIN32_WINDOWS: + if (osInfo.dwMinorVersion == 0) + { + strcpy(info->system, "Windows 95"); + if (osInfo.szCSDVersion[1] == 'C' || osInfo.szCSDVersion[1] == 'B') + strcat(info->system, " OSR2"); + } + else if (osInfo.dwMinorVersion == 10) + { + strcpy(info->system, "Windows 98"); + if (osInfo.szCSDVersion[1] == 'A') + strcat(info->system, " SE"); + } + else if (osInfo.dwMinorVersion == 90) + strcpy(info->system, "Windows Me"); + break; + + case VER_PLATFORM_WIN32_NT: + if (osInfo.dwMajorVersion <= 4) + sprintf(info->system, "Windows NT %d.%d %s (Build %d)", + osInfo.dwMajorVersion, osInfo.dwMinorVersion, osInfo.szCSDVersion, + osInfo.dwBuildNumber); + else if (osInfo.dwMajorVersion == 5) + if (osInfo.dwMinorVersion == 0) + sprintf(info->system, "Windows 2000 %s (Build %d)", + osInfo.szCSDVersion, osInfo.dwBuildNumber & 0xffff); + else + sprintf(info->system, "Windows XP %s (Build %d)", + osInfo.szCSDVersion, osInfo.dwBuildNumber & 0xffff); + + break; + } + + strcpy(info->beServed, "BeServed 1.2.6"); + + info->cpus = systemInfo.dwNumberOfProcessors; + info->maxConnections = BT_MAX_THREADS; + + switch (systemInfo.wProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_MIPS: + strcpy(info->platform, "MIPS"); + break; + + case PROCESSOR_ARCHITECTURE_ALPHA: + strcpy(info->platform, "DEC Alpha"); + break; + + case PROCESSOR_ARCHITECTURE_PPC: + strcpy(info->platform, "PowerPC"); + break; + + case PROCESSOR_ARCHITECTURE_INTEL: + strcpy(info->platform, "Intel x86"); + break; + + default: + strcpy(info->platform, "Unknown"); + } + + // Delay all new session creation. + beginReading(&sessionData); + + info->connections = 0; + for (s = rootSession; s; s = s->next) + if (s->socket != INVALID_SOCKET) + info->connections++; + + info->connections = B_HOST_TO_LENDIAN_INT32(info->connections); + endReading(&sessionData); +} + +// getHostUsers() +// +int getHostUsers(char *buffer) +{ + bt_session_t *s; + char addr[20]; + int len, bufSize; + + // Initialize the buffer to be empty. + buffer[0] = 0; + bufSize = 0; + + // Delay all new session creation. + beginReading(&sessionData); + + for (s = rootSession; s; s = s->next) + if (s->socket != INVALID_SOCKET) + { + uint8 *client_s_addr = (uint8 *) s->client_s_addr; + sprintf(addr, "%d.%d.%d.%d", client_s_addr[0], client_s_addr[1], client_s_addr[2], client_s_addr[3]); + len = strlen(buffer); + strcpy(&buffer[len > 0 ? len + 1 : 0], addr); + bufSize += len + 1; + } + + endReading(&sessionData); + + buffer[bufSize++] = 0; + return bufSize; +} + +// initMimeMap() +// +void initMimeMap() +{ + FILE *fp; + bt_mime_mapping *map; + char mimeLine[256]; + int i, mimeLen; + + fp = fopen("BeServed-MimeMap", "r"); + if (fp) + { + while (fgets(mimeLine, sizeof(mimeLine) - 1, fp)) + { + // Strip off the carriage return. + mimeLine[strlen(mimeLine) - 1] = 0; + + // Create a new MIME map entry. + map = (bt_mime_mapping *) malloc(sizeof(bt_mime_mapping)); + if (!map) + continue; + + map->next = mimeMap; + mimeMap = map; + + // Grab the extension. + for (i = 0; mimeLine[i] != ' '; i++) + map->extension[i] = mimeLine[i]; + + map->extension[i] = 0; + + // Skip to the start of the MIME type. + while (mimeLine[i] == ' ') + i++; + + // Grab the MIME type. + mimeLen = strlen(&mimeLine[i]); + map->mimeType = (char *) malloc(mimeLen + 1); + if (map->mimeType) + strncpy(map->mimeType, &mimeLine[i], mimeLen + 1); + } + + fclose(fp); + } +} + +void closeMimeMap() +{ + bt_mime_mapping *map = mimeMap; + + while (map) + { + map = mimeMap->next; + free(mimeMap->mimeType); + free(mimeMap); + mimeMap = map; + } +} + +void initShares() +{ + FILE *fp; + char buffer[512]; + int i, length; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + { + fileShares[i].name[0] = 0; + fileShares[i].path[0] = 0; + fileShares[i].used = false; + fileShares[i].readOnly = true; + fileShares[i].security = BT_AUTH_NONE; + fileShares[i].rights = NULL; + fileShares[i].next = NULL; + } + + fp = fopen("BeServed-Settings", "r"); + if (fp) + { + while (fgets(buffer, sizeof(buffer) - 1, fp)) + { + length = strlen(buffer); + if (length <= 1 || buffer[0] == '#') + continue; + + if (buffer[length - 1] == '\n') + buffer[--length] = 0; + + if (strncmp(buffer, "share ", 6) == 0) + getFileShare(buffer); + else if (strncmp(buffer, "set ", 4) == 0) + getShareProperty(buffer); + else if (strncmp(buffer, "grant ", 6) == 0) + getGrant(buffer); + else if (strncmp(buffer, "authenticate ", 13) == 0) + getAuthenticate(buffer); + else if (strncmp(buffer, "printer ", 8) == 0) + getPrinter(buffer); + else if (strcmp(buffer, "preload") == 0) + preload = true; + } + + fclose(fp); + } +} + +void initPrinters() +{ + int i; + + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + { + sharedPrinters[i].printerName[0] = 0; + sharedPrinters[i].deviceName[0] = 0; + sharedPrinters[i].spoolDir[0] = 0; + sharedPrinters[i].rights = NULL; + sharedPrinters[i].security = BT_AUTH_NONE; + sharedPrinters[i].used = false; + sharedPrinters[i].killed = false; + } +} + +void loadShares() +{ + int i; + + if (preload) + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + loadFolder(fileShares[i].path); +} + +void getFileShare(const char *buffer) +{ + struct _stat st; + char path[B_PATH_NAME_LENGTH], share[MAX_NAME_LENGTH + 1], *folder; + int i, tok; + + // Skip over SHARE command. + tokPtr = (char *) buffer + (6 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(path, tokBuffer); + tok = getToken(); + if (tok != BT_TOKEN_AS) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + + // Now verify that the share name specified has not already been + // used to share another path. + folder = btGetSharePath(share); + if (folder) + { + winService->LogEvent(EVENTLOG_WARNING_TYPE, EVMSG_DUPLICATE_SHARE, share); + return; + } + + // Check the path to ensure its validity. + if (_stat(path, &st) != 0) + { + winService->LogEvent(EVENTLOG_WARNING_TYPE, EVMSG_INVALID_SHARE_PATH, path); + return; + } + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (!fileShares[i].used) + { + strcpy(fileShares[i].name, share); + strcpy(fileShares[i].path, path); + fileShares[i].used = true; + return; + } + + winService->LogEvent(EVENTLOG_WARNING_TYPE, EVMSG_TOO_MANY_SHARES, share); +} + +void getShareProperty(const char *buffer) +{ + char share[B_FILE_NAME_LENGTH + 1]; + int tok, shareId; + + // Skip over SET command. + tokPtr = (char *) buffer + (4 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + + // Get the index of the share referred to. If the named share cannot be + // found, then abort. + shareId = btGetShareId(share); + if (shareId < 0) + return; + + tok = getToken(); + if (tok == BT_TOKEN_READWRITE) + fileShares[shareId].readOnly = false; +} + +void getGrant(const char *buffer) +{ + char share[MAX_NAME_LENGTH + 1]; + int tok, rights; + bool isGroup = false; + + // Skip over GRANT command. + tokPtr = (char *) buffer + (6 * sizeof(char)); + rights = 0; + + do + { + tok = getToken(); + if (tok == BT_TOKEN_READ) + { + rights |= BT_RIGHTS_READ; + tok = getToken(); + } + else if (tok == BT_TOKEN_WRITE) + { + rights |= BT_RIGHTS_WRITE; + tok = getToken(); + } + else if (tok == BT_TOKEN_PRINT) + { + rights |= BT_RIGHTS_PRINT; + tok = getToken(); + } + } while (tok == BT_TOKEN_COMMA); + + if (tok != BT_TOKEN_ON) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + tok = getToken(); + if (tok != BT_TOKEN_TO) + return; + + tok = getToken(); + if (tok == BT_TOKEN_GROUP) + { + isGroup = true; + tok = getToken(); + } + + if (tok != BT_TOKEN_STRING) + return; + + addUserRights(share, tokBuffer, rights, isGroup); +} + +void getAuthenticate(const char *buffer) +{ + int i, tok; + + // Skip over AUTHENTICATE command. + tokPtr = (char *) buffer + (13 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_WITH) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + // Loop up address for given host. + getAuthServerAddress(tokBuffer); + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + fileShares[i].security = BT_AUTH_BESURE; + + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + sharedPrinters[i].security = BT_AUTH_BESURE; +} + +bool getAuthServerAddress(const char *name) +{ + // Look up address for given host. + struct hostent *ent = gethostbyname(name); + if (ent == NULL) + { + unsigned long addr = inet_addr(tokBuffer); + authServerIP = ntohl(addr); + } + else + authServerIP = ntohl(*((unsigned int *) ent->h_addr)); + + strcpy(authServerName, name); + return true; +} + +void addUserRights(char *share, char *user, int rights, bool isGroup) +{ + bt_printer *printer; + bt_user_rights *ur; + bool isPrinter = false; + int shareId; + + // Now make sure that the rights make sense. If we're granting the + // right to print, we should not have granted the right to read or write. + // We should also be working exclusively with a printer. + if (rights & BT_RIGHTS_PRINT) + { + if (rights & BT_RIGHTS_READ || rights & BT_RIGHTS_WRITE) + return; + + printer = btFindPrinter(share); + if (!printer) + return; + + isPrinter = true; + } + else + { + shareId = btGetShareId(share); + if (shareId < 0) + return; + } + + // Allocate a new user rights structure, populate it, and attach it to + // either a file share or printer. + ur = (bt_user_rights *) malloc(sizeof(bt_user_rights)); + if (ur) + { + ur->user = (char *) malloc(strlen(user) + 1); + if (ur->user) + { + strcpy(ur->user, user); + ur->rights = rights; + ur->isGroup = isGroup; + + if (isPrinter) + { + ur->next = printer->rights; + printer->rights = ur; + } + else + { + ur->next = fileShares[shareId].rights; + fileShares[shareId].rights = ur; + } + } + else + free(ur); + } +} + +void getPrinter(const char *buffer) +{ + bt_printer printer; + DWORD threadId; + int i, tok; + + // Skip over PRINTER command. + tokPtr = (char *) buffer + (8 * sizeof(char)); + + // Now get the name this printer will be shared as. + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(printer.printerName, tokBuffer); + + // Bypass the IS and TYPE keywords. + tok = getToken(); + if (tok != BT_TOKEN_IS) + return; + + tok = getToken(); + if (tok != BT_TOKEN_TYPE) + return; + + // Get the device type of the printer. + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(printer.deviceType, tokBuffer); + + // Bypass the DEVICE keyword. + tok = getToken(); + if (tok != BT_TOKEN_DEVICE) + return; + + // Get the system device name of the printer. + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(printer.deviceName, tokBuffer); + + // Bypass the SPOOLED TO keywords. + tok = getToken(); + if (tok != BT_TOKEN_SPOOLED) + return; + + tok = getToken(); + if (tok != BT_TOKEN_TO) + return; + + // Get the spooling folder, where temporary files will be stored. + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(printer.spoolDir, tokBuffer); + + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + if (!sharedPrinters[i].used) + { + sharedPrinters[i].used = true; + strcpy(sharedPrinters[i].printerName, printer.printerName); + strcpy(sharedPrinters[i].deviceType, printer.deviceType); + strcpy(sharedPrinters[i].deviceName, printer.deviceName); + strcpy(sharedPrinters[i].spoolDir, printer.spoolDir); + sharedPrinters[i].handlerID = CreateThread(NULL, 0, printerThread, (void *) &sharedPrinters[i], 0, &threadId); + break; + } +} + +int getToken() +{ + bool quoted = false; + + tokBuffer[0] = 0; + while (*tokPtr && iswhite(*tokPtr)) + tokPtr++; + + if (*tokPtr == ',') + { + *tokPtr++; + return BT_TOKEN_COMMA; + } + else if (*tokPtr == '\"') + { + quoted = true; + tokPtr++; + } + + if (isalnum(*tokPtr) || *tokPtr == '\\') + { + int i = 0; + while (isalnum(*tokPtr) || isValid(*tokPtr) || (quoted && *tokPtr == ' ')) + if (i < MAX_NAME_LENGTH) + tokBuffer[i++] = *tokPtr++; + else + tokPtr++; + + tokBuffer[i] = 0; + + if (!quoted) + for (i = 0; keywords[i]; i++) + if (stricmp(tokBuffer, keywords[i]) == 0) + return ++i; + + if (quoted) + if (*tokPtr != '\"') + return BT_TOKEN_ERROR; + else + tokPtr++; + + return BT_TOKEN_STRING; + } + + return BT_TOKEN_ERROR; +} + +void startService() +{ + struct sockaddr_in serverAddr, clientAddr; + int client, addrLen; + char flags; + + // Store the length of the socket addressing structure for accept(). + addrLen = sizeof(struct sockaddr_in); + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(BT_TCPIP_PORT); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Create a new socket to receive incoming requests. + server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (server == INVALID_SOCKET) + return; + + // Set the socket option to reuse the current address in case it was + // in use by a prior version of the service that has not yet relinquished + // the socket. + flags = 1; + setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); + + // Bind that socket to the address constructed above. + if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return; + + // Listen for incoming connections. + if (listen(server, 5)) + return; + + // Continually accept incoming connections. When one is found, + // fire off a handler thread to accept commands. + while (running) + { + client = accept(server, (struct sockaddr *) &clientAddr, &addrLen); + if (client != INVALID_SOCKET) + launchThread(client, &clientAddr); + } + + // Close the socket. Technically, I believe we should call shutdown() + // first, but the BeOS header file socket.h indicates that this + // function is not currently working. It is present but may not have + // any effect. + shutdown(server, 2); + closesocket(server); + server = INVALID_SOCKET; +} + +void endService(int sig) +{ + WSACleanup(); + + TerminateThread(hostThread, 0); + closeManagedData(&sessionData); + closeManagedData(&handleData); + + closePrinters(); + closeMimeMap(); + freeFileShares(); + + ubi_trKillTree(&vnidTree, KillNode); + ubi_trKillTree(&nameTree, KillNode); + + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); +} + +void closePrinters() +{ + int i; + + // Close down shared printer spooling threads. + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + if (sharedPrinters[i].used) + { + sharedPrinters[i].killed = true; + waitForThread(sharedPrinters[i].handlerID); + } +} + +// waitForThread() +// +void waitForThread(HANDLE threadId) +{ + DWORD exitCode; + + while (true) + { + // Get the exit code of the thread. If the function fails, the + // thread is invalid and thus already gone. + if (!GetExitCodeThread(threadId, &exitCode)) + break; + + // If we have an exit code, the thread isn't running. + if (exitCode != STILL_ACTIVE) + break; + + // Otherwise, wait and retry. + Sleep(100); + } +} + +// freeFileShares() +// +void freeFileShares() +{ + bt_user_rights *ur, *nextUr; + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + for (ur = fileShares[i].rights; ur; ) + { + nextUr = ur->next; + if (ur->user) + free(ur->user); + + free(ur); + ur = nextUr; + } +} + +// launchThread() +// +void launchThread(int client, struct sockaddr_in *addr) +{ + bt_session_t *s, *cur, *last = NULL; + DWORD threadId; + int count = 0; + + // First verify that the server's not too busy by scanning the list of active + // sessions. This is also useful because we need to eliminate unused sessions + // from the list, i.e., sessions that have closed. + beginWriting(&sessionData); + + s = rootSession; + while (s) + { + if (s->socket == INVALID_SOCKET) + { + if (last) + last->next = s->next; + else + rootSession = s->next; + + cur = s->next; + free(s); + s = cur; + continue; + } + + last = s; + s = s->next; + count++; + } + + // If the total number of valid sessions was less than our allowed maximum, then + // we can create a new session. + if (count < BT_MAX_THREADS) + { + // We need to create an available session for this connection. + bt_session_t *session = (bt_session_t *) malloc(sizeof(bt_session_t)); + if (session) + { + session->socket = client; + session->client_s_addr = addr->sin_addr.s_addr; + session->rootBlock = NULL; + session->killed = false; + session->rights = 0; + session->handlerID = CreateThread(NULL, 0, requestThread, (void *) session, 0, &threadId); + + // Add this to the session list. + session->next = rootSession; + rootSession = session; + endWriting(&sessionData); + return; + } + } + + endWriting(&sessionData); + + // We must have too many threads active, so let the client know we're busy. + sendErrorToClient(client, 0, EBUSY); + shutdown(client, 2); + closesocket(client); +} + +DWORD WINAPI requestThread(LPVOID data) +{ + bt_session_t *session = (bt_session_t *) data; + + if (!session) + return 0; + + session->blockSem = CreateSemaphore(NULL, 1, 1, NULL); + if (session->blockSem) + { + session->rootBlock = NULL; + while (!session->killed && receiveRequest(session)); + CloseHandle(session->blockSem); + } + + shutdown(session->socket, 2); + closesocket(session->socket); + session->socket = INVALID_SOCKET; + return 0; +} + +int receiveRequest(bt_session_t *session) +{ + bt_inPacket packet; + char signature[20], *buffer; + unsigned char command; + int client, sigLen; + int32 length; + + client = session->socket; + + // Read the BeTalk RPC header. + sigLen = strlen(BT_RPC_SIGNATURE); + if (btRecvMsg(client, signature, sigLen, 0) == -1) + return 0; + +// recv(client, &verHi, sizeof(verHi), 0); +// recv(client, &verLo, sizeof(verLo), 0); + + signature[sigLen] = 0; + if (strcmp(signature, BT_RPC_SIGNATURE)) + return 0; + + // Read in the rest of the packet. + if (btRecvMsg(client, (char *) &length, sizeof(int32), 0) == -1) + return 0; + + length = B_LENDIAN_TO_HOST_INT32(length); + if (length == 0 || length > BT_RPC_MAX_PACKET_SIZE) + return 0; + + buffer = (char *) malloc(length + 1); + if (!buffer) + return 0; + + if (btRecvMsg(client, buffer, length, 0) == -1) + { + free(buffer); + return 0; + } + + buffer[length] = 0; + packet.buffer = buffer; + packet.length = length; + packet.offset = 0; + + // Read the transmission ID and command. + command = btRPCGetChar(&packet); + getArguments(session, &packet, command); + free(buffer); + return (command != BT_CMD_QUIT && command != BT_CMD_PREMOUNT); +} + +void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command) +{ + bt_arg_t args[MAX_COMMAND_ARGS]; + int i, client; + bool error; + unsigned char argc, terminator; + int32 xid; + + error = false; + client = session->socket; + argc = btRPCGetChar(packet); + if (argc > MAX_COMMAND_ARGS) + return; + + for (i = 0; i < argc && !error; i++) + { + args[i].type = btRPCGetInt32(packet); + args[i].data = btRPCGetNewString(packet); + if (args[i].data == NULL) + error = true; + } + + if (!error) + { + xid = btRPCGetInt32(packet); + terminator = btRPCGetChar(packet); + if (terminator == BT_CMD_TERMINATOR) + handleRequest(session, xid, command, argc, args); + } + + while (--i >= 0) + free(args[i].data); +} + +void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]) +{ + bool validated = true; + int i, j; + + for (i = 0; dirCommands[i].handler; i++) + if (command == dirCommands[i].command) + { + // We may have received a valid command, but one that is not supported by this + // server. In this case, we'll want to return an operation not supported error, + // as opposed to an invalid command error. + if (!dirCommands[i].supported) + { + sendErrorToClient(session->socket, xid, ENOTSUP); + return; + } + + // Now verify that the argument count is correct, and if so, the type of all + // arguments is correct. If not, an invalid command error is returned. + // Otherise, the command is executed, and the handler returns any necessary + // acknowledgement. + if (argc == dirCommands[i].args) + { + for (j = 0; j < argc; j++) + if (dirCommands[i].argTypes[j] != argv[j].type) + { + validated = false; + break; + } + + if (validated) + { + (*dirCommands[i].handler)(session, xid, argc, argv); + return; + } + } + } + + sendErrorToClient(session->socket, xid, EINVAL); +} + +void sendErrorToClient(int client, unsigned int xid, int error) +{ + bt_outPacket packet; + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +// btRecvMsg() +// +int btRecvMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesRead = 0; + do + { + int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags); + if (bytes == -1) + return -1; + + bytesRead += bytes; + } while (bytesRead < dataLen); + + return bytesRead; +} + +// btRecv() +// +int btRecv(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = recv(sock, (char *) data, dataLen, flags); + if (bytes == 0) + return -1; + else if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +// btSendMsg() +// +int btSendMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesSent = 0; + do + { + int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags); + if (bytes == -1) + return -1; + + bytesSent += bytes; + } while (bytesSent < dataLen); + + return bytesSent; +} + +// btSend() +// +int btSend(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = send(sock, (char *) data, dataLen, flags); + if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +uint32 btSwapInt32(uint32 num) +{ + uint8 byte; + union + { + uint32 value; + uint8 bytes[4]; + } convert; + + convert.value = num; + byte = convert.bytes[0]; + convert.bytes[0] = convert.bytes[3]; + convert.bytes[3] = byte; + byte = convert.bytes[1]; + convert.bytes[1] = convert.bytes[2]; + convert.bytes[2] = byte; + return convert.value; +} + +uint64 btSwapInt64(uint64 num) +{ + uint8 byte; + union + { + uint64 value; + uint8 bytes[8]; + } convert; + + convert.value = num; + byte = convert.bytes[0]; + convert.bytes[0] = convert.bytes[7]; + convert.bytes[7] = byte; + byte = convert.bytes[1]; + convert.bytes[1] = convert.bytes[6]; + convert.bytes[6] = byte; + byte = convert.bytes[2]; + convert.bytes[2] = convert.bytes[5]; + convert.bytes[5] = byte; + byte = convert.bytes[3]; + convert.bytes[3] = convert.bytes[4]; + convert.bytes[4] = byte; + return convert.value; +} + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error) +{ + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + return; + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + btRPCPutInt32(packet, xid); + btRPCPutInt32(packet, 0); + btRPCPutInt32(packet, error); +} + +void btRPCSendAck(int client, bt_outPacket *packet) +{ + if (packet) + if (packet->buffer) + { + *(int32 *)(&packet->buffer[9]) = B_HOST_TO_LENDIAN_INT32(packet->length - 13); + btSendMsg(client, packet->buffer, packet->length, 0); + free(packet->buffer); + } +} + +unsigned char btRPCGetChar(bt_inPacket *packet) +{ + unsigned char value; + + if (packet->offset < packet->length) + value = (unsigned char) packet->buffer[packet->offset]; + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + if (bytes > 0) + memcpy(str, &packet->buffer[packet->offset], bytes); + + str[bytes] = 0; + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return ERANGE; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return ERANGE; + + if (length < bytes) + return ERANGE; + + if (bytes > 0) + memcpy(buffer, &packet->buffer[packet->offset], bytes); + + packet->offset += bytes; + return bytes; +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCGetStat(bt_inPacket *packet, beos_stat *st) +{ + st->st_dev = 0; + st->st_nlink = btRPCGetInt32(packet); + st->st_uid = btRPCGetInt32(packet); + st->st_gid = btRPCGetInt32(packet); + st->st_size = (int32) btRPCGetInt64(packet); + st->st_blksize = btRPCGetInt32(packet); + st->st_rdev = btRPCGetInt32(packet); + st->st_ino = (int32) btRPCGetInt64(packet); + st->st_mode = btRPCGetInt32(packet); + st->st_atime = btRPCGetInt32(packet); + st->st_mtime = btRPCGetInt32(packet); + st->st_ctime = btRPCGetInt32(packet); +} + +void btRPCPutStat(bt_outPacket *packet, beos_stat *st) +{ + if (packet && st) + { + int64 size = (int64) st->st_size; + int64 inode = (int64) st->st_ino; + + btRPCPutInt32(packet, (int) st->st_nlink); + btRPCPutInt32(packet, (int) st->st_uid); + btRPCPutInt32(packet, (int) st->st_gid); + btRPCPutInt64(packet, size); + btRPCPutInt32(packet, (int) 1024); + btRPCPutInt32(packet, (int) st->st_rdev); + btRPCPutInt64(packet, inode); + btRPCPutInt32(packet, (int) st->st_mode); + btRPCPutInt32(packet, (int) st->st_atime); + btRPCPutInt32(packet, (int) st->st_mtime); + btRPCPutInt32(packet, (int) st->st_ctime); + } +} + +//////////////////////////////////////////////////////////////////// + +bt_node *btGetNodeFromVnid(vnode_id vnid) +{ + return (bt_node *) ubi_trFind(&vnidTree, &vnid); +} + +// btAddHandle() +// +void btAddHandle(vnode_id dir_vnid, vnode_id file_vnid, char *name) +{ + bt_node *vnidNode, *nameNode, *dirNode; + + // We don't store the references to the current and the parent directory. + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + return; + + beginWriting(&handleData); + + // Obtain the parent node. If no parent vnid is provided, then this must be + // the root node. The parent of the root node is NULL, but it should be the + // only node for which this is true. + if (dir_vnid) + dirNode = btGetNodeFromVnid(dir_vnid); + else + dirNode = NULL; + + // If a node already exists with the given vnid, then it is either a symbolic + // link or an attempt to add the same node again, such as when mounting or + // walking a directory tree. If we find a matching vnid whose parent directory + // and name also match, this is a duplicate and can be ignored. + if (btGetNodeFromVnid(file_vnid)) + { + endWriting(&handleData); + return; + } + + // Allocate a new node for the vnid and name-based trees. A separate node must exist for + // each tree or the tree structure will go haywire. + vnidNode = (bt_node *) malloc(sizeof(bt_node)); + if (vnidNode == NULL) + { + endWriting(&handleData); + return; + } + + nameNode = (bt_node *) malloc(sizeof(bt_node)); + if (nameNode == NULL) + { + free(vnidNode); + endWriting(&handleData); + return; + } + + // Allocate memory for the file name itself. This prevents huge memory consumption used by + // a static buffer that assumes the worst case file name length. + vnidNode->name = (char *) malloc(strlen(name) + 1); + if (vnidNode->name == NULL) + { + free(nameNode); + free(vnidNode); + endWriting(&handleData); + return; + } + + // Copy the name into the allocated buffer. + strcpy(vnidNode->name, name); + + nameNode->name = strdup(vnidNode->name); + if (nameNode->name == NULL) + { + free(vnidNode->name); + free(nameNode); + free(vnidNode); + endWriting(&handleData); + return; + } + + // Copy over the vnid, and parent node. + vnidNode->invalid = nameNode->invalid = false; + vnidNode->vnid = nameNode->vnid = file_vnid; + vnidNode->parent = nameNode->parent = dirNode; + + // Now insert the new nodes into the tree. + ubi_trInsert(&vnidTree, vnidNode, &vnidNode->vnid, NULL); + ubi_trInsert(&nameTree, nameNode, nameNode, NULL); + + endWriting(&handleData); +} + +// btRemoveHandle() +// +void btRemoveHandle(vnode_id vnid) +{ + bt_node *deadVnidNode, *deadNameNode; + + beginWriting(&handleData); + + deadVnidNode = (bt_node *) ubi_trFind(&vnidTree, &vnid); + if (deadVnidNode) + { + ubi_trRemove(&vnidTree, deadVnidNode); + + deadNameNode = (bt_node *) ubi_trFind(&nameTree, deadVnidNode); + if (deadNameNode) + ubi_trRemove(&nameTree, deadNameNode); + } + + endWriting(&handleData); +} + +// btPurgeNodes() +// +void btPurgeNodes(vnode_id vnid) +{ + bt_node *curNode; + ubi_trNodePtr cur, next; + ubi_trRootPtr tree; + ubi_trRootPtr trees[] = { &vnidTree, &nameTree, NULL }; + int i; + + beginWriting(&handleData); + + // First loop through, marking this node and all its children as invalid. + for (i = 0, tree = trees[i]; trees[i]; i++) + { + cur = ubi_trFirst(tree->root); + while (cur) + { + next = ubi_trNext(cur); + + curNode = (bt_node *) cur; + if (curNode->vnid == vnid || btIsAncestorNode(vnid, curNode)) + curNode->invalid = true; + + cur = next; + } + + // Now loop through again, removing all invalid nodes. This prevents removing + // a parent node and all its children being orphaned (with invalid pointers + // back to the destroyed parent). + cur = ubi_trFirst(tree->root); + while (cur) + { + next = ubi_trNext(cur); + + curNode = (bt_node *) cur; + if (curNode->invalid) + { + ubi_trRemove(&vnidTree, curNode); + free(curNode); + } + + cur = next; + } + } + + endWriting(&handleData); +} + +// btIsAncestorNode() +// +bool btIsAncestorNode(vnode_id vnid, bt_node *node) +{ + bt_node *curNode = node->parent; + + while (curNode) + { + if (curNode->vnid == vnid) + return true; + + curNode = curNode->parent; + } + + return false; +} + +// btGetLocalFileName() +// +char *btGetLocalFileName(char *path, vnode_id vnid) +{ + bt_node *node, *nodeStack[100]; + int stackSize; + + path[0] = 0; + stackSize = 1; + + beginReading(&handleData); + + node = btGetNodeFromVnid(vnid); + if (node == NULL) + { + endReading(&handleData); + return NULL; + } + + nodeStack[0] = node; + while ((node = node->parent) != NULL) + nodeStack[stackSize++] = node; + + while (--stackSize >= 0) + { + strcat(path, nodeStack[stackSize]->name); + if (stackSize) + { + int length = strlen(path); + if (length > 0 && path[length - 1] != '\\') + strcat(path, "\\"); + } + } + + endReading(&handleData); + return path; +} + +bt_node *btFindNode(bt_node *parent, char *fileName) +{ + bt_node search, *node; + + // Initialize the node for tree searching purposes. + search.parent = parent; + search.name = strdup(fileName); + if (search.name == NULL) + return NULL; + + beginReading(&handleData); + node = (bt_node *) ubi_trFind(&nameTree, &search); + endReading(&handleData); + + free(search.name); + return node; +} + +char *btGetSharePath(char *shareName) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (stricmp(fileShares[i].name, shareName) == 0) + return fileShares[i].path; + + return NULL; +} + +int btGetShareId(char *shareName) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (stricmp(fileShares[i].name, shareName) == 0) + return i; + + return -1; +} + +int btGetShareIdByPath(char *path) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (stricmp(fileShares[i].path, path) == 0) + return i; + + return -1; +} + +// btFindPrinter() +// +bt_printer *btFindPrinter(char *printerName) +{ + int i; + + for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) + if (sharedPrinters[i].used) + if (stricmp(printerName, sharedPrinters[i].printerName) == 0) + return &sharedPrinters[i]; + + return NULL; +} + +void btGetRootPath(vnode_id vnid, char *path) +{ + bt_node *curNode; + + beginReading(&handleData); + + curNode = btGetNodeFromVnid(vnid); + while (curNode && curNode->parent) + curNode = curNode->parent; + + if (curNode) + strcpy(path, curNode->name); + else + path[0] = 0; + + endReading(&handleData); +} + +uint32 btGetWinInode(const char *path) +{ + const int MAX_FOLDER_NESTING = 100; + char *folders[MAX_FOLDER_NESTING + 1]; + char newPath[B_PATH_NAME_LENGTH + 1]; + int i, level, len, charSum; + + // Subdivide the path into its components. + char *p, *s = strdup(path); + level = 0; + folders[level++] = s; + for (p = s; *p; p++) + if (*p == '\\') + { + folders[level++] = p + 1; + *p = 0; + } + + folders[level] = 0; + + // Now look through the folders, to see if any are . and .. references. + for (i = 0; i < level; i++) + if (*folders[i]) + if (strcmp(folders[i], ".") == 0) + folders[i] = NULL; + else if (strcmp(folders[i], "..") == 0) + { + int j = i; + folders[i] = 0; + while (j > 0 && folders[j] == NULL) + j--; + + if (j >= 0) + folders[j] = 0; + } + + // Now reconstruct the path without the folders eliminated above. + newPath[0] = 0; + for (i = 0; i < level; i++) + if (folders[i]) + { + strcat(newPath, folders[i]); + if (i < level - 1) + strcat(newPath, "\\"); + } + + // If we eliminated folders at the end of the path, the level will have + // resulted in a trailing backslash. + len = strlen(newPath); + if (newPath[len - 1] == '\\') + newPath[--len] = 0; + + // Now compute the checksum, i.e., inode number, using the revised path. + free(s); + p = newPath; + for (charSum = len = 0; *p; p++, len++) + charSum += (*p * len); + + return ((len << 24) + charSum); +} + +int btGetBeosStat(char *fileName, beos_stat *st) +{ + struct _stat _st; + + if (_stat(fileName, &_st) != 0) + return BEOS_ENOENT; + + st->st_atime = _st.st_atime; + st->st_blksize = 1024; + st->st_ctime = _st.st_ctime; + st->st_dev = 0; + st->st_gid = 0; + st->st_uid = 0; + st->st_ino = btGetWinInode(fileName); + st->st_mode = _st.st_mode; + st->st_mtime = _st.st_mtime; + st->st_nlink = 0; + st->st_rdev = 0; + st->st_size = _st.st_size; + + return B_OK; +} + +void btMakePath(char *path, char *dir, char *file) +{ + int length; + + strcpy(path, dir); + length = strlen(path); + if (length > 0) + if (path[length - 1] != '\\') + strcat(path, "\\"); + + strcat(path, file); +} + +//////////////////////////////////////////////////////////////////// + +int btPreMount(bt_session_t *session, char *shareName) +{ + // Look for the specified share name. If it can't be found, check to see if it's + // a printer. If not, then there is no such resource available on this host. + int shareId = btGetShareId(shareName); + if (shareId < 0) + { + bt_printer *printer = btFindPrinter(shareName); + if (!printer) + return BEOS_ENOENT; + + return printer->security; + } + + return fileShares[shareId].security; +} + +int btMount(bt_session_t *session, char *shareName, char *user, char *password) +{ + bt_user_rights *ur; + struct stat st; + char *path, *groups[MAX_GROUPS_PER_USER]; + int i, shareId; + bool authenticated = false; + + // Initialize the groups array. We may need to release the memory later. + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + groups[i] = NULL; + + // Look for the specified share name. If it can't be found, it must no longer be + // shared on this host. + shareId = btGetShareId(shareName); + if (shareId < 0) + return BEOS_ENOENT; + + if (fileShares[shareId].security != BT_AUTH_NONE) + { + // Authenticate the user with name/password. + authenticated = authenticateUser(user, password); + if (!authenticated) + return BEOS_EACCES; + + // Does the authenticated user have any rights on this file share? + session->rights = 0; + for (ur = fileShares[shareId].rights; ur; ur = ur->next) + if (!ur->isGroup && stricmp(ur->user, user) == 0) + session->rights |= ur->rights; + + getUserGroups(user, groups); + for (ur = fileShares[shareId].rights; ur; ur = ur->next) + if (ur->isGroup) + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + if (groups[i] && stricmp(ur->user, groups[i]) == 0) + { + session->rights |= ur->rights; + break; + } + + // Free the memory occupied by the group list. + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + if (groups[i]) + free(groups[i]); + + // If no rights have been granted, deny access. + if (session->rights == 0) + return BEOS_EACCES; + + // If write access has been globally disabled, this user's rights must be + // correspondingly synchronized. + if (fileShares[shareId].readOnly) + session->rights = BT_RIGHTS_READ; + } + else + session->rights = fileShares[shareId].readOnly + ? BT_RIGHTS_READ + : BT_RIGHTS_READ | BT_RIGHTS_WRITE; + + // Make sure the folder we want to share still exists. + path = fileShares[shareId].path; + if (stat(path, &st) != 0) + return BEOS_ENOENT; + + if (!S_ISDIR(st.st_mode)) + return BEOS_EACCES; + + // Mark this session as owned by this user. + strcpy(session->user, user); + return B_OK; +} + +int btGetFSInfo(fs_info *fsInfo, char *path) +{ + DWORD secsPerClstr, bytesPerSec, freeClstrs, totalClstrs; + char rootDir[5]; + + // We only want the root directory specification, not the entire path. + strncpy(rootDir, path, 3); + rootDir[3] = 0; + + if (GetDiskFreeSpace(rootDir, &secsPerClstr, &bytesPerSec, &freeClstrs, &totalClstrs)) + { + fsInfo->block_size = bytesPerSec; + fsInfo->total_blocks = secsPerClstr * totalClstrs; + fsInfo->free_blocks = secsPerClstr * freeClstrs; + return B_OK; + } + + return ENOTSUP; +} + +int btLookup(char *fileName) +{ + struct _stat st; + if (_stat(fileName, &st) != 0) + return BEOS_ENOENT; + + return B_OK; +} + +int btStat(char *pathBuf, vnode_id vnid, beos_stat *st) +{ + char *fileName; + int error; + + fileName = btGetLocalFileName(pathBuf, vnid); + if (fileName) + { + error = btGetBeosStat(fileName, st); + return error; + } + + return BEOS_ENOENT; +} + +int btReadDir(char *pathBuf, vnode_id dir_vnid, long **dir, vnode_id *file_vnid, char *filename, beos_stat *st) +{ + struct _finddata_t fileInfo; + char *folder, path[B_PATH_NAME_LENGTH]; + long result = -1; + + if (dir_vnid == 0 || !file_vnid || !filename) + return EINVAL; + + if (!*dir) + { + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + char search[B_PATH_NAME_LENGTH]; + btMakePath(search, folder, "*.*"); + result = _findfirst(search, &fileInfo); + *dir = (long *) malloc(sizeof(long *)); + memcpy(*dir, &result, sizeof(result)); + } + } + else + result = _findnext((long) **dir, &fileInfo); + + if (result != -1) + { + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + btMakePath(path, folder, fileInfo.name); + if (btGetBeosStat(path, st) != 0) + return BEOS_ENOENT; + + strcpy(filename, fileInfo.name); + *file_vnid = (vnode_id) st->st_ino; + btAddHandle(dir_vnid, *file_vnid, filename); + return B_OK; + } + } + else if (*dir) + { + _findclose((long) **dir); + return BEOS_ENOENT; + } + + return EINVAL; +} + +int32 btRead(char *pathBuf, vnode_id vnid, beos_off_t pos, int32 len, char *buffer) +{ + char *path; + int bytes; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + FILE *fp = fopen(path, "rb"); + if (!fp) + return EACCES; + + fseek(fp, (int) pos, SEEK_SET); + bytes = fread(buffer, 1, len, fp); + fclose(fp); + + buffer[bytes] = 0; + return bytes; + } + + return 0; +} + +int32 btWrite(bt_session_t *session, vnode_id vnid, beos_off_t pos, int32 len, int32 totalLen, char *buffer) +{ + bt_block *block; + + // If we've been given a total length, then we have a new buffered write + // session coming. A block will need to be allocated. + if (totalLen > 0) + { + // Make sure we don't have a wildly inaccurate total length to allocate. + if (totalLen > 10 * 1024 * 1024) + return 0; + + // Allocate a new buffered I/O block. + block = (bt_block *) malloc(sizeof(bt_block)); + if (block) + { + block->vnid = vnid; + block->pos = pos; + block->len = totalLen; + block->count = 0; + + block->buffer = (char *) malloc(totalLen + 1); + if (!block->buffer) + { + free(block); + return 0; + } + + btInsertWriteBlock(session, block); + } + else + return 0; + } + else + { + block = btGetWriteBlock(session, vnid); + if (!block) + return 0; + } + + memcpy(block->buffer + block->count, buffer, len); + block->count += len; + return len; +} + +// btGetWriteBlock() +// +bt_block *btGetWriteBlock(bt_session_t *session, vnode_id vnid) +{ + bt_block *block; + + WaitForSingleObject(session->blockSem, INFINITE); + + block = session->rootBlock; + while (block && block->vnid != vnid) + block = block->next; + + ReleaseSemaphore(session->blockSem, 1, NULL); + return block; +} + +// btInsertWriteBlock() +// +void btInsertWriteBlock(bt_session_t *session, bt_block *block) +{ + WaitForSingleObject(session->blockSem, INFINITE); + + block->next = session->rootBlock; + block->prev = NULL; + if (session->rootBlock) + session->rootBlock->prev = block; + + session->rootBlock = block; + + ReleaseSemaphore(session->blockSem, 1, NULL); +} + +int btCommit(bt_session_t *session, vnode_id vnid) +{ + bt_block *block; + char *path; + int file; + + // Get the full path for the specified file. + path = btGetLocalFileName(session->pathBuffer, vnid); + if (!path) + return BEOS_ENOENT; + + // Obtain the buffered I/O block. If one can't be found, no buffered I/O + // session was started for this vnode. + block = btGetWriteBlock(session, vnid); + if (!block) + return BEOS_ENOENT; + + // Open the file for writing. + file = _open(path, _O_WRONLY | _O_CREAT | _O_BINARY); + if (file < 0) + return errno; + + WaitForSingleObject(session->blockSem, INFINITE); + + // Write the data. + _lseek(file, (int32) block->pos, SEEK_SET); + _write(file, block->buffer, block->len); + + btRemoveWriteBlock(session, block); + ReleaseSemaphore(session->blockSem, 1, NULL); + + _close(file); + return B_OK; +} + +void btRemoveWriteBlock(bt_session_t *session, bt_block *block) +{ + // If we're removing the root, then adjust the root block pointer. + if (session->rootBlock == block) + session->rootBlock = block->next; + + // If there's a previous block, it should now point beyond this block. + if (block->prev) + block->prev->next = block->next; + + // If there's a next block, it hsould now point to the current predecessor. + if (block->next) + block->next->prev = block->prev; + + // Release the memory used by this block. + free(block->buffer); + free(block); +} + +int btCreate(char *pathBuf, vnode_id dir_vnid, char *name, int omode, int perms, vnode_id *file_vnid) +{ + beos_stat st; + char path[B_PATH_NAME_LENGTH], *folder; + int fh; + + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + btMakePath(path, folder, name); + fh = open(path, O_WRONLY | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE); + if (fh == -1) + return errno; + else + { + close(fh); + if (btGetBeosStat(path, &st) == 0) + { + *file_vnid = (vnode_id) st.st_ino; + btAddHandle(dir_vnid, *file_vnid, name); + } + else + return BEOS_EACCES; + } + } + + return B_OK; +} + +int btTruncate(char *pathBuf, vnode_id vnid, int64 len) +{ + char *path; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + FILE *fp = fopen(path, "w"); + fclose(fp); + return B_OK; + } + + return BEOS_EACCES; +} + +// btCreateDir() +// +int btCreateDir(char *pathBuf, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, beos_stat *st) +{ + char path[B_PATH_NAME_LENGTH], *folder; + + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + btMakePath(path, folder, name); + if (_mkdir(path) == -1) + return errno; + + if (btGetBeosStat(path, st) != 0) + return BEOS_ENOENT; + + *file_vnid = (vnode_id) st->st_ino; + btAddHandle(dir_vnid, *file_vnid, name); + return B_OK; + } + + return BEOS_ENOENT; +} + +// btDeleteDir() +// +int btDeleteDir(char *pathBuf, vnode_id vnid, char *name) +{ + struct _stat st; + char path[B_PATH_NAME_LENGTH], *folder; + + folder = btGetLocalFileName(pathBuf, vnid); + if (folder) + { + btMakePath(path, folder, name); + if (_stat(path, &st) != 0) + return errno; + + if (_rmdir(path) == -1) + return errno; + + btPurgeNodes(btGetWinInode(path)); + return B_OK; + } + + return BEOS_ENOENT; +} + +// btRename() +// +int btRename(char *pathBuf, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName) +{ + struct _stat st; + char oldPath[B_PATH_NAME_LENGTH], newPath[B_PATH_NAME_LENGTH], *oldFolder, *newFolder; + + oldFolder = btGetLocalFileName(pathBuf, old_vnid); + if (oldFolder) + { + btMakePath(oldPath, oldFolder, oldName); + + newFolder = btGetLocalFileName(pathBuf, new_vnid); + if (newFolder) + { + btMakePath(newPath, newFolder, newName); + + if (_stat(oldPath, &st) != 0) + return errno; + + btPurgeNodes(btGetWinInode(oldPath)); + + if (rename(oldPath, newPath) == -1) + return errno; + + return B_OK; + } + } + + return BEOS_ENOENT; +} + +// btUnlink() +// +int btUnlink(char *pathBuf, vnode_id vnid, char *name) +{ + struct _stat st; + char path[B_PATH_NAME_LENGTH], *folder; + int error; + + folder = btGetLocalFileName(pathBuf, vnid); + if (folder) + { + btMakePath(path, folder, name); + + // Obtain the inode (vnid) of the specified file through stat(). + if (_stat(path, &st) != 0) + return errno; + + // Construct a dummy file descriptor and cause it to be removed from + // the list. + btRemoveHandle(btGetWinInode(path)); + + error = unlink(path); + return (error == -1 ? errno : B_OK); + } + + return BEOS_EACCES; +} + +int btReadLink(char *pathBuf, vnode_id vnid, char *buffer, int length) +{ + return BEOS_ENOENT; +} + +int btSymLink(char *pathBuf, vnode_id vnid, char *name, char *dest) +{ + return BEOS_ENOENT; +} + +int btWStat(char *pathBuf, vnode_id vnid, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime) +{ + struct _utimbuf ftimes; + struct _stat st; + char *path; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { +// if (mask & WSTAT_MODE) +// chmod(path, mode); + +// if (mask & WSTAT_UID) +// chown(path, uid, -1); + +// if (mask & WSTAT_GID) +// chown(path, -1, gid); + +// if (mask & WSTAT_SIZE) +// truncate(path, size); + + if (_stat(path, &st) == 0) + if (mask & WSTAT_ATIME || mask & WSTAT_MTIME) + { + ftimes.actime = mask & WSTAT_ATIME ? atime : st.st_atime; + ftimes.modtime = mask & WSTAT_MTIME ? mtime : st.st_mtime; + _utime(path, &ftimes); + } + + return B_OK; + } + + return BEOS_ENOENT; +} + +int btReadAttrib(char *pathBuf, vnode_id vnid, char *name, char *buffer) +{ + bt_mime_mapping *map; + char *path; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + char *ext = strrchr(path, '.'); + if (ext) + { + ext++; + for (map = mimeMap; map; map = map->next) + if (stricmp(ext, map->extension) == 0) + { + strcpy(buffer, map->mimeType); + return (strlen(buffer)); + } + } + } + + return 0; +} + +int btAuthenticate(char *resource, char *user, char *password) +{ + bt_user_rights *ur, *rootUr; + bt_printer *printer; + char *groups[MAX_GROUPS_PER_USER]; + int i, rights, share; + bool authenticated = false; + + // Determine if the resource is a file share or a printer. + share = btGetShareId(resource); + if (share >= 0) + { + if (fileShares[share].security == BT_AUTH_NONE) + return B_OK; + + rootUr = fileShares[share].rights; + } + else + { + printer = btFindPrinter(resource); + if (printer) + if (printer->security == BT_AUTH_NONE) + return B_OK; + + rootUr = printer->rights; + } + + // Authenticate the user with name/password. + authenticated = authenticateUser(user, password); + if (!authenticated) + return BEOS_EACCES; + + // Does the authenticated user have any rights on this file share? + rights = 0; + for (ur = rootUr; ur; ur = ur->next) + if (!ur->isGroup && stricmp(ur->user, user) == 0) + rights |= ur->rights; + + // Does the authenticated user belong to any groups that have any rights on this + // file share? + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + groups[i] = NULL; + + getUserGroups(user, groups); + for (ur = rootUr; ur; ur = ur->next) + if (ur->isGroup) + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + if (groups[i] && stricmp(ur->user, groups[i]) == 0) + { + rights |= ur->rights; + break; + } + + // Free the memory occupied by the group list. + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + if (groups[i]) + free(groups[i]); + + // If no rights have been granted, deny access. + if (!rights) + return BEOS_EACCES; + + return B_OK; +} + +//////////////////////////////////////////////////////////////////// + +void netbtPreMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, security; + + client = session->socket; + security = btPreMount(session, argv[0].data); + btRPCCreateAck(&packet, xid, security); + btRPCSendAck(session->socket, &packet); +} + +void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + vnode_id vnid; + int client, error; + char *shareName = argv[0].data; + char *user = argv[1].data; + char *password = argv[2].data; + + client = session->socket; + + error = btMount(session, shareName, user, password, &vnid); + if (error == B_OK) + { + // Record this session having logged in to a specific share. + session->share = btGetShareId(shareName); + session->logon = time(NULL); + + // Now send the client a response with the root vnid; + btRPCCreateAck(&packet, xid, error); + btRPCPutInt64(&packet, vnid); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + fs_info info; + + client = session->socket; + + error = btGetFSInfo(&info, fileShares[session->share].path); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCPutInt32(&packet, info.block_size); + btRPCPutInt32(&packet, info.total_blocks); + btRPCPutInt32(&packet, info.free_blocks); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + beos_stat st; + int client, error; + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + + client = session->socket; + + error = btLookup(session->pathBuffer, dir_vnid, argv[1].data, &file_vnid); + if (error == B_OK) + error = btStat(session->pathBuffer, file_vnid, &st); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt64(&packet, file_vnid); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + const int MAX_FOLDER_ENTRIES = 128; + bt_outPacket packet; + beos_stat st; + int client, error; + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + long *dir; + char filename[B_PATH_NAME_LENGTH]; + int entries = 0; + + client = session->socket; + + dir = (long *)(*((int32 *) argv[1].data)); + error = btReadDir(session->pathBuffer, dir_vnid, &dir, &file_vnid, filename, &st); + + if (error != B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + btRPCCreateAck(&packet, xid, B_OK); + while (error == B_OK) + { + btRPCPutInt64(&packet, file_vnid); + btRPCPutString(&packet, filename, strlen(filename)); + btRPCPutInt32(&packet, (int32) dir); + btRPCPutStat(&packet, &st); + + if (++entries >= MAX_FOLDER_ENTRIES) + break; + + error = btReadDir(session->pathBuffer, dir_vnid, &dir, &file_vnid, filename, &st); + btRPCPutInt32(&packet, error); + } + + // If we exhausted the list of directory entries without filling + // the buffer, add an error message that will prevent the client + // from requesting further entries. + if (entries < MAX_FOLDER_ENTRIES) + btRPCPutInt32(&packet, BEOS_ENOENT); + + btRPCSendAck(client, &packet); +} + +void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + beos_stat info; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + error = btStat(session->pathBuffer, vnid, &info); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCPutStat(&packet, &info); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + vnode_id vnid = *((vnode_id *) argv[0].data); + beos_off_t pos = *((beos_off_t *) argv[1].data); + int32 len = *((int32 *) argv[2].data); + int32 bytes = 0; + + client = session->socket; + + session->ioBuffer[len] = 0; + bytes = btRead(session->pathBuffer, vnid, pos, len, session->ioBuffer); + + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutString(&packet, session->ioBuffer, bytes); + btRPCSendAck(client, &packet); +} + +void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + int client; + vnode_id vnid = *((vnode_id *) argv[0].data); + beos_off_t pos = *((beos_off_t *) argv[1].data); + int32 len = *((int32 *) argv[2].data); + int32 totalLen = *((int32 *) argv[3].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (session->rights & BT_RIGHTS_WRITE) + btWrite(session, vnid, pos, len, totalLen, argv[4].data); +} + +void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + beos_stat st; + int client, error; + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + int omode = *((int *) argv[2].data); + int perms = *((int *) argv[3].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, BEOS_EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btCreate(session->pathBuffer, dir_vnid, argv[1].data, omode, perms, &file_vnid); + if (error == B_OK) + error = btStat(session->pathBuffer, file_vnid, &st); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt64(&packet, file_vnid); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, BEOS_EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btTruncate(session->pathBuffer, vnid, *((int64 *) argv[1].data)); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, BEOS_EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btUnlink(session->pathBuffer, vnid, argv[1].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id old_vnid = *((vnode_id *) argv[0].data); + vnode_id new_vnid = *((vnode_id *) argv[2].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, BEOS_EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btRename(session->pathBuffer, old_vnid, argv[1].data, new_vnid, argv[3].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + beos_stat st; + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, BEOS_EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btCreateDir(session->pathBuffer, dir_vnid, argv[1].data, *((int *) argv[2].data), &file_vnid, &st); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt64(&packet, file_vnid); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); +} + +void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, BEOS_EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btDeleteDir(session->pathBuffer, vnid, argv[1].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + int32 mask = *((int32 *) argv[1].data); + int32 mode = *((int32 *) argv[2].data); + int32 uid = *((int32 *) argv[3].data); + int32 gid = *((int32 *) argv[4].data); + int64 size = (int64) *((int32 *) argv[5].data); + int32 atime = *((int32 *) argv[6].data); + int32 mtime = *((int32 *) argv[7].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, BEOS_EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btWStat(session->pathBuffer, vnid, mask, mode, uid, gid, size, atime, mtime); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, bytesRead; + + client = session->socket; + + if (stricmp(argv[1].data, "BEOS:TYPE") == 0) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + bytesRead = btReadAttrib(session->pathBuffer, vnid, argv[1].data, session->attrBuffer); + if (bytesRead > 0) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt32(&packet, (int32) bytesRead + 1); + btRPCPutString(&packet, session->attrBuffer, bytesRead + 1); + btRPCSendAck(client, &packet); + return; + } + } + + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, bytesRead; + + client = session->socket; + if (strcmp(argv[1].data, "BEOS:TYPE") == 0) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + bytesRead = btReadAttrib(session->pathBuffer, vnid, argv[1].data, session->attrBuffer); + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt32(&packet, B_STRING_TYPE); + btRPCPutInt64(&packet, bytesRead + 1); + btRPCSendAck(client, &packet); + return; + } + + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, ENOTSUP); + btRPCSendAck(client, &packet); +} + +void netbtCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + vnode_id vnid = *((vnode_id *) argv[0].data); + + client = session->socket; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, BEOS_EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btCommit(session, vnid); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtPrintJobNew(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + char jobId[MAX_NAME_LENGTH]; + char *printerName = argv[0].data; + char *user = argv[1].data; + char *password = argv[2].data; + char *jobName = argv[3].data; + + client = session->socket; + + error = btPrintJobNew(printerName, user, password, session->client_s_addr, jobName, jobId); + btRPCCreateAck(&packet, xid, error); + if (error == B_OK) + btRPCPutString(&packet, jobId, strlen(jobId)); + + btRPCSendAck(client, &packet); +} + +void netbtPrintJobData(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + char *printerName = argv[0].data; + char *jobId = argv[1].data; + char *jobData = argv[2].data; + int32 dataLen = *((int32 *) argv[3].data); + + client = session->socket; + + error = btPrintJobData(printerName, jobId, jobData, dataLen); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtPrintJobCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + char *printerName = argv[0].data; + char *jobId = argv[1].data; + + client = session->socket; + + error = btPrintJobCommit(printerName, jobId); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + char *resource = argv[0].data; + char *user = argv[1].data; + char *password = argv[2].data; + + client = session->socket; + + error = btAuthenticate(resource, user, password); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, B_OK); + btRPCSendAck(client, &packet); +} + +/* +bool IsValidUser(char *user, char *domain, char *password) +{ + HANDLE hUser, hTok; + OSVERSIONINFO osInfo; + bool authenticated; + + authenticated = false; + + osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (GetVersionEx(&osInfo)) + if (osInfo.dwPlatformId != VER_PLATFORM_WIN32_NT) + return true; + + hTok = 0; + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hTok)) + { + TOKEN_PRIVILEGES tp; + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (LookupPrivilegeValue(0, SE_TCB_NAME, &tp.Privileges[0].Luid)) + if (AdjustTokenPrivileges(hTok, FALSE, &tp, 0, NULL, NULL)) + if (LogonUser(user, domain, password, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &hUser)) + { + CloseHandle(hUser); + authenticated = true; + } + + CloseHandle(hTok); + } + + return authenticated; +} +*/ + +void loadFolder(const char *path) +{ + struct _finddata_t fileInfo; + struct _stat st; + char *search; + long dir, result; + uint32 dir_vnid; + + search = (char *) malloc(MAX_PATH); + if (search == NULL) + return; + + dir_vnid = btGetWinInode(path); + sprintf(search, "%s\\*.*", path); + + dir = result = _findfirst(search, &fileInfo); + while (result != -1) + { + btMakePath(search, (char *) path, fileInfo.name); + btAddHandle(dir_vnid, btGetWinInode(search), fileInfo.name); + + _stat(search, &st); + if (st.st_mode & _S_IFDIR) + if (strcmp(fileInfo.name, ".") && strcmp(fileInfo.name, "..")) + loadFolder(search); + + result = _findnext(dir, &fileInfo); + } + + _findclose(dir); + free(search); +} + + + +//////// + +void KillNode(ubi_trNodePtr node) +{ + bt_node *bn = (bt_node *) node; + free(bn->name); + free(node); +} + +int CompareVnidNodes(ubi_trItemPtr item, ubi_trNodePtr node) +{ + vnode_id vnid1 = *((vnode_id *) item); + vnode_id vnid2 = ((bt_node *) node)->vnid; + if (vnid1 < vnid2) + return -1; + else if (vnid1 > vnid2) + return 1; + else + return 0; +} + +int CompareNameNodes(ubi_trItemPtr item, ubi_trNodePtr node) +{ + bt_node *node1 = (bt_node *) item; + bt_node *node2 = (bt_node *) node; + + if (node1->parent < node2->parent) + return -1; + else if (node1->parent > node2->parent) + return 1; + else + return strcmp(node1->name, node2->name); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BlowFish.cpp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BlowFish.cpp new file mode 100644 index 0000000000..32d6f39cfe --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BlowFish.cpp @@ -0,0 +1,191 @@ +/* blowfish.c */ + +#include "stdafx.h" + +#include "blowfish.h" +#include "BlowFishTable.h" + +#define N 16 +#define noErr 0 +#define DATAERROR -1 +#define KEYBYTES 8 + +unsigned long F(blf_ctx *bc, unsigned long x) +{ + unsigned long a; + unsigned long b; + unsigned long c; + unsigned long d; + unsigned long y; + + d = x & 0x00FF; + x >>= 8; + c = x & 0x00FF; + x >>= 8; + b = x & 0x00FF; + x >>= 8; + a = x & 0x00FF; + y = bc->S[0][a] + bc->S[1][b]; + y = y ^ bc->S[2][c]; + y = y + bc->S[3][d]; + + return y; +} + +void Blowfish_encipher(blf_ctx *bc, unsigned long *xl, unsigned long *xr) +{ + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = 0; i < N; ++i) + { + Xl = Xl ^ bc->P[i]; + Xr = F(bc, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ bc->P[N]; + Xl = Xl ^ bc->P[N + 1]; + + *xl = Xl; + *xr = Xr; +} + +void Blowfish_decipher(blf_ctx *bc, unsigned long *xl, unsigned long *xr) +{ + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = N + 1; i > 1; --i) + { + Xl = Xl ^ bc->P[i]; + Xr = F(bc, Xl) ^ Xr; + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + } + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ bc->P[1]; + Xl = Xl ^ bc->P[0]; + + *xl = Xl; + *xr = Xr; +} + +short InitializeBlowfish(blf_ctx *bc, unsigned char key[], int keybytes) +{ + short i; + short j; + short k; + unsigned long data; + unsigned long datal; + unsigned long datar; + + /* initialise p & s-boxes without file read */ + for (i = 0; i < N+2; i++) + { + bc->P[i] = bfp[i]; + } + for (i = 0; i < 256; i++) + { + bc->S[0][i] = ks0[i]; + bc->S[1][i] = ks1[i]; + bc->S[2][i] = ks2[i]; + bc->S[3][i] = ks3[i]; + } + + j = 0; + for (i = 0; i < N + 2; ++i) + { + data = 0x00000000; + for (k = 0; k < 4; ++k) + { + data = (data << 8) | key[j]; + j = j + 1; + if (j >= keybytes) + { + j = 0; + } + } + bc->P[i] = bc->P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for (i = 0; i < N + 2; i += 2) + { + Blowfish_encipher(bc, &datal, &datar); + + bc->P[i] = datal; + bc->P[i + 1] = datar; + } + + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 256; j += 2) + { + + Blowfish_encipher(bc, &datal, &datar); + + bc->S[i][j] = datal; + bc->S[i][j + 1] = datar; + } + } + return 0; +} + +void blf_key (blf_ctx *c, unsigned char *k, int len) +{ + InitializeBlowfish(c, k, len); +} + +void blf_enc(blf_ctx *c, unsigned long *data, int blocks) +{ + unsigned long *d; + int i; + + d = data; + for (i = 0; i < blocks; i++) + { + Blowfish_encipher(c, d, d+1); + d += 2; + } +} + +void blf_dec(blf_ctx *c, unsigned long *data, int blocks) +{ + unsigned long *d; + int i; + + d = data; + for (i = 0; i < blocks; i++) + { + Blowfish_decipher(c, d, d+1); + d += 2; + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BlowFish.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BlowFish.h new file mode 100644 index 0000000000..4a500951c1 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BlowFish.h @@ -0,0 +1,19 @@ +/* blowfish.h */ + +#define UWORD32 unsigned long +#define UBYTE08 unsigned char + +#define MAXKEYBYTES 56 /* 448 bits */ + +typedef struct +{ + unsigned long S[4][256], P[18]; +} blf_ctx; + +unsigned long F(blf_ctx *, unsigned long x); +void Blowfish_encipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +void Blowfish_decipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +short InitializeBlowfish(blf_ctx *, unsigned char key[], int keybytes); +void blf_enc(blf_ctx *c, unsigned long *data, int blocks); +void blf_dec(blf_ctx *c, unsigned long *data, int blocks); +void blf_key(blf_ctx *c, unsigned char *key, int len); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BlowFishTable.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BlowFishTable.h new file mode 100644 index 0000000000..3547ee1d19 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/BlowFishTable.h @@ -0,0 +1,280 @@ +/* bf_tab.h: Blowfish P-box and S-box tables */ + + +static UWORD32 bfp[] = +{ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b, +}; + +static UWORD32 ks0[] = +{ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + }; + static UWORD32 ks1[]= + { + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 +}; +static UWORD32 ks2[] = +{ + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 +}; +static UWORD32 ks3[] = +{ + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/NTServApp.aps b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/NTServApp.aps new file mode 100644 index 0000000000..988208bbde Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/NTServApp.aps differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/NTServApp.rc b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/NTServApp.rc new file mode 100644 index 0000000000..97e8527252 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/NTServApp.rc @@ -0,0 +1,73 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// + +#include "NTServMsg.rc" + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/STDAFX.H b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/STDAFX.H new file mode 100644 index 0000000000..021cb9c781 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/STDAFX.H @@ -0,0 +1,14 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#include // MFC core and standard components +#include // MFC extensions +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows 95 Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT +//#include // MFC socket extensions + + + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/authentication.cpp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/authentication.cpp new file mode 100644 index 0000000000..50a9bb1f21 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/authentication.cpp @@ -0,0 +1,266 @@ +#include "stdafx.h" + +#include "beCompat.h" +#include "betalk.h" +#include "authentication.h" + +#include "ctype.h" +#include "signal.h" +#include "stdlib.h" + +extern bool getAuthServerAddress(const char *name); + +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket); +int btRPCConnect(unsigned int serverIP, int port); +bool btRPCSend(int session, bt_outPacket *outPacket); +bool btRPCCheckSignature(int session); +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); + + +int btRPCConnect(unsigned int serverIP, int port) +{ + struct sockaddr_in serverAddr; + int session; + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(port); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(serverIP); + + // Create a new socket to receive incoming requests. + session = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (session == INVALID_SOCKET) + return INVALID_SOCKET; + + // Bind that socket to the address constructed above. + if (connect(session, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return INVALID_SOCKET; + + return session; +} + +bool btRPCSend(int session, bt_outPacket *outPacket) +{ + // The XID will be 0. + btRPCPutInt32(outPacket, 0); + btRPCPutChar(outPacket, BT_CMD_TERMINATOR); + + if (btSendMsg(session, outPacket->buffer, outPacket->length, 0) == -1) + return false; + + return true; +} + +bool btRPCCheckSignature(int session) +{ + char signature[20]; + unsigned int sigLen; + + sigLen = strlen(BT_RPC_SIGNATURE); + memset(signature, 0, sigLen); + if (btRecvMsg(session, signature, sigLen, 0) == -1) + return false; + + // Check the signature's validity. + signature[sigLen] = 0; + return (strcmp(signature, BT_RPC_SIGNATURE) == 0); +} + +// btRPCSimpleCall() +// +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket) +{ + struct timeval timeout; + bt_inPacket *inPacket; + fd_set sockSet; + char *buffer; + int session; + int32 xid, length; + + // Establish a connection with the requested server, on the requested port. + // If we can't connect, abort and return a NULL packet. + inPacket = NULL; + session = btRPCConnect(serverIP, port); + if (session == INVALID_SOCKET) + return NULL; + + // If we connected, send the requested RPC packet. If the packet cannot be + // sent, the connection has dropped and we'll abort the call. + if (!btRPCSend(session, outPacket)) + { + close(session); + return NULL; + } + + // Set a reasonable timeout period. Select() is used in leiu of alarm() because + // select() also aborts on error, alarm() effects all threads in a process. + FD_ZERO(&sockSet); + timeout.tv_sec = 8; + timeout.tv_usec = 0; + + // Block in select() waiting for activity. This will block until data is available + // or until a socket error is pending. + FD_SET(session, &sockSet); + select(session + 1, &sockSet, NULL, NULL, &timeout); + + // If our socket has data pending, then read the incoming RPC response packet. + // This should consist of a valid RPC signature, a tranaction ID (xid), the length + // of the variable data, and the data itself. + if (FD_ISSET(session, &sockSet)) + if (btRPCCheckSignature(session)) + { + if (btRecvMsg(session, &xid, sizeof(int32), 0) == -1 || + btRecvMsg(session, &length, sizeof(int32), 0) == -1) + goto abortCall; + + // Now allocate a buffer of the appropriate length. If one cannot be + // allocated, we won't be able to store incoming information and the call + // must be aborted. + xid = B_LENDIAN_TO_HOST_INT32(xid); + length = B_LENDIAN_TO_HOST_INT32(length); + if (length > 0 && length < BT_RPC_MAX_PACKET_SIZE) + { + buffer = (char *) malloc(length + 1); + if (buffer) + { + // Read the remaining packet contents. The btRecv() function takes + // care of restarting the recv() when signal interrupts occur. It + // will always return -1 on error, even upon orderly shutdown of the peer. + if (btRecvMsg(session, buffer, length, 0) == -1) + { + free(buffer); + goto abortCall; + } + + // Terminate the buffer. + buffer[length] = 0; + + // Allocate a new incoming packet and set its buffer and length. + inPacket = (bt_inPacket *) malloc(sizeof(bt_inPacket)); + if (inPacket) + { + inPacket->buffer = buffer; + inPacket->length = length; + inPacket->offset = 0; + } + else + free(buffer); + } + } + } + + // Execution can naturally lead here or we can jump here from a failed attempt to + // send or receive an RPC packet. The socket is closed and the current incoming + // packet returned, which will be NULL upon failure. +abortCall: + shutdown(session, 2); + close(session); + return inPacket; +} + +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length) +{ + bt_outPacket *packet; + + packet = (bt_outPacket *) malloc(sizeof(bt_outPacket)); + if (!packet) + return NULL; + + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + { + free(packet); + return NULL; + } + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + +// btRPCPutChar(packet, BT_RPC_VERSION_HI); +// btRPCPutChar(packet, BT_RPC_VERSION_LO); + btRPCPutInt32(packet, 7 + (8 * argc) + length); + btRPCPutChar(packet, command); + btRPCPutChar(packet, argc); + + return packet; +} + +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length) +{ + btRPCPutInt32(packet, type); + btRPCPutInt32(packet, length); + btRPCPutBinary(packet, data, length); +} + +bool authenticateUser(char *user, char *password) +{ + extern char *authServerName; + extern unsigned int authServerIP; + bt_outPacket *outPacket; + bt_inPacket *inPacket; + bool authenticated = false; + int error; + + getAuthServerAddress(authServerName); + + outPacket = btRPCPutHeader(BT_CMD_AUTH, 2, strlen(user) + BT_AUTH_TOKEN_LENGTH); + if (outPacket) + { + btRPCPutArg(outPacket, B_STRING_TYPE, user, strlen(user)); + btRPCPutArg(outPacket, B_STRING_TYPE, password, BT_AUTH_TOKEN_LENGTH); + inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket); + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + authenticated = true; + + free(inPacket->buffer); + free(inPacket); + } + + free(outPacket->buffer); + free(outPacket); + } + + return authenticated; +} + +void getUserGroups(char *user, char **groups) +{ + extern char *authServerName; + extern unsigned int authServerIP; + bt_outPacket *outPacket; + bt_inPacket *inPacket; + int i, error; + + getAuthServerAddress(authServerName); + + outPacket = btRPCPutHeader(BT_CMD_WHICHGROUPS, 1, strlen(user)); + if (outPacket) + { + btRPCPutArg(outPacket, B_STRING_TYPE, user, strlen(user)); + inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket); + if (inPacket) + { + i = 0; + error = btRPCGetInt32(inPacket); + while (error == B_OK) + { + groups[i++] = btRPCGetNewString(inPacket); + error = btRPCGetInt32(inPacket); + } + + free(inPacket->buffer); + free(inPacket); + } + + free(outPacket->buffer); + free(outPacket); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/authentication.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/authentication.h new file mode 100644 index 0000000000..8c784ff771 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/authentication.h @@ -0,0 +1,2 @@ +bool authenticateUser(char *user, char *password); +void getUserGroups(char *user, char **groups); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/beCompat.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/beCompat.h new file mode 100644 index 0000000000..923574e740 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/beCompat.h @@ -0,0 +1,152 @@ +#ifndef B_OK + +#include +#include +//#include +//#include +//#include + +#define B_OK 0 +#define B_ENTRY_NOT_FOUND ENOENT +#define B_PATH_NAME_LENGTH 1024 +#define B_FILE_NAME_LENGTH 256 +#define B_OS_NAME_LENGTH 32 +#define B_INTERRUPTED 1 + +#define BEOS_ENOENT 2147508227 +#define BEOS_EACCES 2147483650 +#define BEOS_ENOMEM 2147483648 +#define BEOS_EINVAL 0 + +#ifndef true +#define true 1 +#define false 0 +#endif + +#define WSTAT_MODE 0x0001 +#define WSTAT_UID 0x0002 +#define WSTAT_GID 0x0004 +#define WSTAT_SIZE 0x0008 +#define WSTAT_ATIME 0x0010 +#define WSTAT_MTIME 0x0020 +#define WSTAT_CRTIME 0x0040 + +#define B_COMMON_SETTINGS_DIRECTORY ".\\" +#define B_COMMON_SYSTEM_DIRECTORY ".\\" + +#define ENOTSUP 1 + +#define lstat(f, s) stat(f, s) +#define S_ISDIR(m) ((m) & _S_IFDIR) + +typedef char int8; +typedef long int32; +typedef LONGLONG int64; +typedef unsigned char uint8; +typedef unsigned long uint32; +typedef ULONGLONG uint64; + +typedef uint64 vnode_id; +typedef uint64 beos_ino_t; +typedef uint64 beos_off_t; +typedef unsigned long beos_dev_t; +typedef HANDLE sem_id; +typedef HANDLE thread_id; + +#define LITTLE_ENDIAN + +#ifdef LITTLE_ENDIAN +#define B_LENDIAN_TO_HOST_INT32(x) (x) +#define B_LENDIAN_TO_HOST_INT64(x) (x) +#define B_HOST_TO_LENDIAN_INT32(x) (x) +#define B_HOST_TO_LENDIAN_INT64(x) (x) +#else +#define B_LENDIAN_TO_HOST_INT32(x) btSwapInt32(x) +#define B_LENDIAN_TO_HOST_INT64(x) btSwapInt64(x) +#define B_HOST_TO_LENDIAN_INT32(x) btSwapInt32(x) +#define B_HOST_TO_LENDIAN_INT64(x) btSwapInt64(x) +#endif + +uint32 btSwapInt32(uint32 num); +uint64 btSwapInt64(uint64 num); + + +enum { + B_ANY_TYPE = 'ANYT', + B_BOOL_TYPE = 'BOOL', + B_CHAR_TYPE = 'CHAR', + B_COLOR_8_BIT_TYPE = 'CLRB', + B_DOUBLE_TYPE = 'DBLE', + B_FLOAT_TYPE = 'FLOT', + B_GRAYSCALE_8_BIT_TYPE = 'GRYB', + B_INT64_TYPE = 'LLNG', + B_INT32_TYPE = 'LONG', + B_INT16_TYPE = 'SHRT', + B_INT8_TYPE = 'BYTE', + B_MESSAGE_TYPE = 'MSGG', + B_MESSENGER_TYPE = 'MSNG', + B_MIME_TYPE = 'MIME', + B_MONOCHROME_1_BIT_TYPE = 'MNOB', + B_OBJECT_TYPE = 'OPTR', + B_OFF_T_TYPE = 'OFFT', + B_PATTERN_TYPE = 'PATN', + B_POINTER_TYPE = 'PNTR', + B_POINT_TYPE = 'BPNT', + B_RAW_TYPE = 'RAWT', + B_RECT_TYPE = 'RECT', + B_REF_TYPE = 'RREF', + B_RGB_32_BIT_TYPE = 'RGBB', + B_RGB_COLOR_TYPE = 'RGBC', + B_SIZE_T_TYPE = 'SIZT', + B_SSIZE_T_TYPE = 'SSZT', + B_STRING_TYPE = 'CSTR', + B_TIME_TYPE = 'TIME', + B_UINT64_TYPE = 'ULLG', + B_UINT32_TYPE = 'ULNG', + B_UINT16_TYPE = 'USHT', + B_UINT8_TYPE = 'UBYT', + B_MEDIA_PARAMETER_TYPE = 'BMCT', + B_MEDIA_PARAMETER_WEB_TYPE = 'BMCW', + B_MEDIA_PARAMETER_GROUP_TYPE= 'BMCG', + + /* deprecated, do not use */ + B_ASCII_TYPE = 'TEXT' /* use B_STRING_TYPE instead */ +}; + + +typedef struct fs_info +{ + beos_dev_t dev; + beos_ino_t root; + uint32 flags; +// beos_off_t block_size; + uint32 block_size; + beos_off_t io_size; +// beos_off_t total_blocks; +// beos_off_t free_blocks; + uint32 total_blocks; + uint32 free_blocks; + beos_off_t total_nodes; + beos_off_t free_nodes; + char device_name[128]; + char volume_name[B_FILE_NAME_LENGTH]; + char fsh_name[B_OS_NAME_LENGTH]; +} fs_info; + +typedef struct beos_stat +{ + uint32 st_dev; + uint32 st_nlink; + uint32 st_uid; + uint32 st_gid; + uint32 st_size; + uint32 st_blksize; + uint32 st_rdev; + uint32 st_ino; + uint32 st_mode; + uint32 st_atime; + uint32 st_mtime; + uint32 st_ctime; +} beos_stat; + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/betalk.h new file mode 100644 index 0000000000..8e2e034ccb --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/betalk.h @@ -0,0 +1,246 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +#include //linux +#include +#include +#include +#include +#include +#include +#include +#include // windows +#include +#include // windows +#include +#include // windows +#include // windows +#include // windows + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 +#define BT_REQ_PRINTER_PROBE 6 + +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRINTER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 32768 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 64 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_PRELOAD 19 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'' || (c)=='\\') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct userRights +{ + char *user; + int rights; + bool isGroup; + struct userRights *next; +} bt_user_rights; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket packet; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +void btRPCGetStat(bt_inPacket *packet, beos_stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, beos_stat *st); + +bt_rpccall * btRPCInvoke(int session, bt_outPacket *packet); +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/icon1.ico b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/icon1.ico new file mode 100644 index 0000000000..bb974eb0ac Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/icon1.ico differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/msg00001.bin b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/msg00001.bin new file mode 100644 index 0000000000..5a8c29f6bb Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/msg00001.bin differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/myservice.cpp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/myservice.cpp new file mode 100644 index 0000000000..6c861c8257 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/myservice.cpp @@ -0,0 +1,101 @@ +// FILE: MyService.cpp +// +// DESCRIPTION: +// This file contains the implementation of a Windows NT service, encapsulated in a +// class derived from the CNTService class. Contained herein are initialization +// routines, log file operations, and code for the listening threads. +// + +// Visual C++ Definitions +#include "stdafx.h" +#include "afxmt.h" +#include "winreg.h" +#include "winsvc.h" + +// Standard C Definitions +#include "io.h" +#include "direct.h" + +// Application-specific Definitions +#include "NTServApp.h" +#include "myservice.h" + + +CMyService::CMyService() : CNTService("BeServed", "BeServed File and Print Services") +{ +} + + +BOOL CMyService::OnInit() +{ + extern void BeServedStartup(CMyService *service); + char path[_MAX_PATH], *pStr; + + // Get the executable file path + GetModuleFileName(NULL, path, sizeof(path)); + pStr = strrchr(path, '\\'); + if (pStr) + *pStr = 0; + + SetCurrentDirectory(path); + + BeServedStartup(this); + return true; +} + +// OnStop() +// +void CMyService::OnStop() +{ + extern void endService(int); + endService(0); +} + +// Restart() +// +void CMyService::Restart() +{ + OnStop(); + OnInit(); +} + +// IsRunning() +// +BOOL CMyService::IsRunning() +{ + return (m_bIsRunning); +} + +// Run() +// +BOOL CMyService::Run() +{ + extern void loadShares(); + extern void startService(); + loadShares(); + startService(); + return true; +} + +// Process user control requests +BOOL CMyService::OnUserControl(DWORD dwOpcode) +{ + extern void restartService(); + + switch (dwOpcode) + { + case SERVICE_USER_CONTROL_HUP: + restartService(); + return true; + + default: + break; + } + + return false; +} + +void CMyService::InitLogging() +{ +} + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/myservice.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/myservice.h new file mode 100644 index 0000000000..71d77fc272 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/myservice.h @@ -0,0 +1,23 @@ +// myservice.h + +#include "ntservice.h" + + +#define SERVICE_USER_CONTROL_HUP SERVICE_CONTROL_USER + 1 + + +class CMyService : public CNTService +{ +public: + CMyService(); + virtual BOOL OnInit(); + virtual void OnStop(); + virtual BOOL Run(); + virtual void Restart(); + virtual BOOL OnUserControl(DWORD dwOpcode); + BOOL IsRunning(); + +private: + // Initialization + void InitLogging(); +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/node.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/node.h new file mode 100644 index 0000000000..6187df417b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/node.h @@ -0,0 +1,23 @@ +#ifndef _NODE_H_ +#define _NODE_H_ + +#include "beCompat.h" +#include "betalk.h" + +typedef struct btnode +{ + vnode_id vnid; + char name[B_FILE_NAME_LENGTH]; + int refCount; + bool invalid; + struct btnode *next; + struct btnode *prev; + struct btnode *parent; +} bt_node; + +typedef bt_node caddr_t; + +int compareNodeVnid(caddr_t node1, caddr_t node2); +int compareNodeName(caddr_t node1, caddr_t node2); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservapp.cpp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservapp.cpp new file mode 100644 index 0000000000..8441cbcabf --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservapp.cpp @@ -0,0 +1,22 @@ +// NTService.cpp +// +// This is the main program file containing the entry point. + +#include "stdafx.h" +#include "winsvc.h" + +#include "NTServApp.h" +#include "myservice.h" + +int main(int argc, char *argv[]) +{ + // Create the service object + CMyService MyService; + + // Parse for standard arguments (install, uninstall, version etc.) + if (!MyService.ParseStandardArgs(argc, argv)) + MyService.StartService(); + + // When we get here, the service has been stopped + return MyService.m_Status.dwWin32ExitCode; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservapp.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservapp.h new file mode 100644 index 0000000000..71d561a197 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservapp.h @@ -0,0 +1,5 @@ +// NTService.h + +#include +#include +#include "ntservice.h" diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.001 b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.001 new file mode 100644 index 0000000000..7881eced6c --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.001 @@ -0,0 +1,452 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.10 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +!IF "$(CFG)" == "" +CFG=ntservice - Win32 Debug +!MESSAGE No configuration specified. Defaulting to ntservice - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "ntservice - Win32 Release" && "$(CFG)" !=\ + "ntservice - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ntservice.mak" CFG="ntservice - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ntservice - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ntservice - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "ntservice - Win32 Debug" +RSC=rc.exe +CPP=cl.exe + +!IF "$(CFG)" == "ntservice - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "WinRel" +# PROP BASE Intermediate_Dir "WinRel" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinRel" +# PROP Intermediate_Dir "WinRel" +OUTDIR=.\WinRel +INTDIR=.\WinRel + +ALL : ".\WinDebug\ntservice.exe" + +CLEAN : + -@erase "$(INTDIR)\CCLIENT.OBJ" + -@erase "$(INTDIR)\cgiapp.obj" + -@erase "$(INTDIR)\CLISTEN.OBJ" + -@erase "$(INTDIR)\FTPClient.obj" + -@erase "$(INTDIR)\myservice.obj" + -@erase "$(INTDIR)\NTServApp.obj" + -@erase "$(INTDIR)\NTServApp.res" + -@erase "$(INTDIR)\NTService.obj" + -@erase "$(INTDIR)\SERVICE.OBJ" + -@erase "$(INTDIR)\SimpleSocket.obj" + -@erase ".\WinDebug\ntservice.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +.\WinRel\NTService.bsc : $(OUTDIR) $(BSC32_SBRS) +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /YX /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /YX /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE"\ + /Fp"$(INTDIR)/ntservice.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\WinRel/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/NTServApp.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/ntservice.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /profile /machine:I386 /out:"WinDebug/ntservice.exe" +# SUBTRACT LINK32 /map /debug /nodefaultlib +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /profile\ + /machine:I386 /out:"WinDebug/ntservice.exe" +LINK32_OBJS= \ + "$(INTDIR)\CCLIENT.OBJ" \ + "$(INTDIR)\cgiapp.obj" \ + "$(INTDIR)\CLISTEN.OBJ" \ + "$(INTDIR)\FTPClient.obj" \ + "$(INTDIR)\myservice.obj" \ + "$(INTDIR)\NTServApp.obj" \ + "$(INTDIR)\NTServApp.res" \ + "$(INTDIR)\NTService.obj" \ + "$(INTDIR)\SERVICE.OBJ" \ + "$(INTDIR)\SimpleSocket.obj" + +".\WinDebug\ntservice.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ntservice - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "WinDebug" +# PROP BASE Intermediate_Dir "WinDebug" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WinDebug" +# PROP Intermediate_Dir "WinDebug" +OUTDIR=.\WinDebug +INTDIR=.\WinDebug + +ALL : "$(OUTDIR)\ntservice.exe" + +CLEAN : + -@erase "$(INTDIR)\CCLIENT.OBJ" + -@erase "$(INTDIR)\cgiapp.obj" + -@erase "$(INTDIR)\CLISTEN.OBJ" + -@erase "$(INTDIR)\FTPClient.obj" + -@erase "$(INTDIR)\myservice.obj" + -@erase "$(INTDIR)\NTServApp.obj" + -@erase "$(INTDIR)\NTServApp.res" + -@erase "$(INTDIR)\NTService.obj" + -@erase "$(INTDIR)\SERVICE.OBJ" + -@erase "$(INTDIR)\SimpleSocket.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\ntservice.exe" + -@erase "$(OUTDIR)\ntservice.ilk" + -@erase "$(OUTDIR)\ntservice.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +.\WinDebug\NTService.bsc : $(OUTDIR) $(BSC32_SBRS) +# ADD BASE CPP /nologo /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /YX /c +# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /O2 /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /YX /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MT /W3 /Gm /GX /Zi /O2 /D "_DEBUG" /D "WIN32" /D "_CONSOLE"\ + /Fp"$(INTDIR)/ntservice.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\WinDebug/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/NTServApp.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/ntservice.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 +# SUBTRACT LINK32 /map /nodefaultlib +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /incremental:yes\ + /pdb:"$(OUTDIR)/ntservice.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)/ntservice.exe" +LINK32_OBJS= \ + "$(INTDIR)\CCLIENT.OBJ" \ + "$(INTDIR)\cgiapp.obj" \ + "$(INTDIR)\CLISTEN.OBJ" \ + "$(INTDIR)\FTPClient.obj" \ + "$(INTDIR)\myservice.obj" \ + "$(INTDIR)\NTServApp.obj" \ + "$(INTDIR)\NTServApp.res" \ + "$(INTDIR)\NTService.obj" \ + "$(INTDIR)\SERVICE.OBJ" \ + "$(INTDIR)\SimpleSocket.obj" + +"$(OUTDIR)\ntservice.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Target + +# Name "ntservice - Win32 Release" +# Name "ntservice - Win32 Debug" + +!IF "$(CFG)" == "ntservice - Win32 Release" + +!ELSEIF "$(CFG)" == "ntservice - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\NTService.cpp +DEP_CPP_NTSER=\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\stdafx.h"\ + + +"$(INTDIR)\NTService.obj" : $(SOURCE) $(DEP_CPP_NTSER) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\NTServApp.cpp +DEP_CPP_NTSERV=\ + ".\logger.h"\ + ".\myservice.h"\ + ".\NTServApp.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\stdafx.h"\ + + +"$(INTDIR)\NTServApp.obj" : $(SOURCE) $(DEP_CPP_NTSERV) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\NTServApp.rc +DEP_RSC_NTSERVA=\ + ".\MSG00001.bin"\ + ".\ntservmsg.rc"\ + + +"$(INTDIR)\NTServApp.res" : $(SOURCE) $(DEP_RSC_NTSERVA) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\NTServMsg.mc + +!IF "$(CFG)" == "ntservice - Win32 Release" + +!ELSEIF "$(CFG)" == "ntservice - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\myservice.cpp + +!IF "$(CFG)" == "ntservice - Win32 Release" + +DEP_CPP_MYSER=\ + ".\cclient.h"\ + ".\cgiapp.h"\ + ".\clisten.h"\ + ".\FTPClient.h"\ + ".\logger.h"\ + ".\myservice.h"\ + ".\NTServApp.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\SimpleSocket.h"\ + ".\stdafx.h"\ + {$(INCLUDE)}"\MSWSOCK.H"\ + {$(INCLUDE)}"\WINSOCK2.H"\ + + +"$(INTDIR)\myservice.obj" : $(SOURCE) $(DEP_CPP_MYSER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ntservice - Win32 Debug" + +DEP_CPP_MYSER=\ + ".\cclient.h"\ + ".\cgiapp.h"\ + ".\clisten.h"\ + ".\FTPClient.h"\ + ".\logger.h"\ + ".\myservice.h"\ + ".\NTServApp.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\SimpleSocket.h"\ + ".\stdafx.h"\ + {$(INCLUDE)}"\WINSOCK2.H"\ + + +"$(INTDIR)\myservice.obj" : $(SOURCE) $(DEP_CPP_MYSER) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\SERVICE.CPP +DEP_CPP_SERVI=\ + ".\cclient.h"\ + ".\cgiapp.h"\ + ".\logger.h"\ + ".\myservice.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\SimpleSocket.h"\ + ".\stdafx.h"\ + {$(INCLUDE)}"\MSWSOCK.H"\ + {$(INCLUDE)}"\WINSOCK2.H"\ + + +"$(INTDIR)\SERVICE.OBJ" : $(SOURCE) $(DEP_CPP_SERVI) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\CLISTEN.CPP +DEP_CPP_CLIST=\ + ".\clisten.h"\ + ".\logger.h"\ + ".\myservice.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\SimpleSocket.h"\ + ".\stdafx.h"\ + {$(INCLUDE)}"\MSWSOCK.H"\ + {$(INCLUDE)}"\WINSOCK2.H"\ + + +"$(INTDIR)\CLISTEN.OBJ" : $(SOURCE) $(DEP_CPP_CLIST) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\cgiapp.cpp +DEP_CPP_CGIAP=\ + ".\cclient.h"\ + ".\cgiapp.h"\ + ".\logger.h"\ + ".\myservice.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\SimpleSocket.h"\ + ".\stdafx.h"\ + {$(INCLUDE)}"\MSWSOCK.H"\ + {$(INCLUDE)}"\WINSOCK2.H"\ + + +"$(INTDIR)\cgiapp.obj" : $(SOURCE) $(DEP_CPP_CGIAP) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\CCLIENT.CPP +DEP_CPP_CCLIE=\ + ".\cclient.h"\ + ".\cgiapp.h"\ + ".\logger.h"\ + ".\myservice.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\SimpleSocket.h"\ + ".\stdafx.h"\ + {$(INCLUDE)}"\MSWSOCK.H"\ + {$(INCLUDE)}"\WINSOCK2.H"\ + + +"$(INTDIR)\CCLIENT.OBJ" : $(SOURCE) $(DEP_CPP_CCLIE) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\SimpleSocket.cpp +DEP_CPP_SIMPL=\ + ".\logger.h"\ + ".\myservice.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\SimpleSocket.h"\ + ".\stdafx.h"\ + {$(INCLUDE)}"\MSWSOCK.H"\ + {$(INCLUDE)}"\WINSOCK2.H"\ + + +"$(INTDIR)\SimpleSocket.obj" : $(SOURCE) $(DEP_CPP_SIMPL) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\FTPClient.cpp +DEP_CPP_FTPCL=\ + ".\FTPClient.h"\ + ".\logger.h"\ + ".\myservice.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\SimpleSocket.h"\ + ".\stdafx.h"\ + {$(INCLUDE)}"\MSWSOCK.H"\ + {$(INCLUDE)}"\WINSOCK2.H"\ + + +"$(INTDIR)\FTPClient.obj" : $(SOURCE) $(DEP_CPP_FTPCL) "$(INTDIR)" + + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.cpp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.cpp new file mode 100644 index 0000000000..13cb12753c --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.cpp @@ -0,0 +1,495 @@ +// NTService.cpp +// +// Implementation of CNTService + +// Visual C++ Definitions +#include "stdafx.h" +#include "winreg.h" +#include "winsvc.h" + +// Standard C Definitions +#include "stdio.h" + +// Application-specific Definitions +#include "NTService.h" + +CNTService* CNTService::m_pThis = NULL; + + +CNTService::CNTService(LPCTSTR pServiceName, LPCSTR pDisplayName) +{ + OSVERSIONINFO osInfo; + + // copy the address of the current object so we can access it from + // the static member callback functions. + // WARNING: This limits the application to only one CNTService object. + m_pThis = this; + + // Set the default service name and version + memset(m_szServiceName, 0, sizeof(m_szServiceName)); + memset(m_szDisplayName, 0, sizeof(m_szDisplayName)); + strncpy(m_szServiceName, pServiceName, sizeof(m_szServiceName) - 1); + strncpy(m_szDisplayName, pDisplayName, sizeof(m_szDisplayName) - 1); + m_hEventSource = NULL; + + // set up the initial service status + m_hServiceStatus = NULL; + m_Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + m_Status.dwCurrentState = SERVICE_STOPPED; + m_Status.dwControlsAccepted = SERVICE_ACCEPT_STOP; + m_Status.dwWin32ExitCode = 0; + m_Status.dwServiceSpecificExitCode = 0; + m_Status.dwCheckPoint = 0; + m_Status.dwWaitHint = 0; + m_bIsRunning = FALSE; + + // Determine if we're running on a Windows 9x platform, including Windows Me. + // If so, we won't be able to support Windows NT services. + osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (GetVersionEx(&osInfo)) + m_bIsWindows9x = (osInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); +} + +CNTService::~CNTService() +{ + DebugMsg("CNTService::~CNTService()"); + + if (!m_bIsWindows9x) + if (m_hEventSource) + DeregisterEventSource(m_hEventSource); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// Default command line argument parsing + +// Returns TRUE if it found an arg it recognised, FALSE if not +// Note: processing some arguments causes output to stdout to be generated. +BOOL CNTService::ParseStandardArgs(int argc, char* argv[]) +{ + if (argc <= 1) + return FALSE; + + if (m_bIsWindows9x) + return TRUE; + + if (_stricmp(argv[1], "-version") == 0) + { + // Report version information + printf("%s 1.2.5\n", m_szServiceName); + printf("The service is %s installed.\n", IsInstalled() ? "currently" : "not"); + return TRUE; + } + else if (_stricmp(argv[1], "-install") == 0) + { + // Install the service + if (IsInstalled()) + printf("%s is already installed.\n", m_szServiceName); + else if (Install()) + printf("%s installed.\n", m_szServiceName); + else + printf("%s failed to install. Error %d\n", m_szServiceName, GetLastError()); + + return TRUE; + } + else if (_stricmp(argv[1], "-remove") == 0) + { + // Uninstall the service + if (!IsInstalled()) + printf("%s is not installed\n", m_szServiceName); + else if (Uninstall()) + { + // Get the executable file path + char szFilePath[_MAX_PATH]; + ::GetModuleFileName(NULL, szFilePath, sizeof(szFilePath)); + printf("%s removed. (You must delete the file (%s) yourself.)\n", m_szServiceName, szFilePath); + } + else printf("Could not remove %s. Error %d\n", m_szServiceName, GetLastError()); + + return TRUE; + } + + // Return FALSE here because the arguments were invalid + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// Install/uninstall routines + +// Test if the service is currently installed +BOOL CNTService::IsInstalled() +{ + BOOL bResult = FALSE; + + if (!m_bIsWindows9x) + { + // Open the Service Control Manager + SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hSCM) + { + // Try to open the service + SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_CONFIG); + if (hService) + { + bResult = TRUE; + ::CloseServiceHandle(hService); + } + + ::CloseServiceHandle(hSCM); + } + } + + return bResult; +} + +BOOL CNTService::Install() +{ + HKEY hKey = NULL; + DWORD dwData; + char szFilePath[_MAX_PATH], szKey[256]; + + // Don't attempt to install on Windows 9x. + if (m_bIsWindows9x) + return TRUE; + + // Open the Service Control Manager + SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (!hSCM) + return FALSE; + + // Get the executable file path + GetModuleFileName(NULL, szFilePath, sizeof(szFilePath)); + + // Create the service + SC_HANDLE hService = CreateService(hSCM, m_szServiceName, m_szDisplayName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, szFilePath, NULL, NULL, NULL, NULL, NULL); + if (!hService) + { + CloseServiceHandle(hSCM); + return FALSE; + } + + // make registry entries to support logging messages + // Add the source name as a subkey under the Application + // key in the EventLog service portion of the registry. + strcpy(szKey, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"); + strcat(szKey, m_szServiceName); + if (RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey) != ERROR_SUCCESS) + { + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return FALSE; + } + + // Add the Event ID message-file name to the 'EventMessageFile' subkey. + RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ, (CONST BYTE *) szFilePath, strlen(szFilePath) + 1); + + // Set the supported types flags. + dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; + RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD, (CONST BYTE *) &dwData, sizeof(DWORD)); + RegCloseKey(hKey); + + LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_INSTALLED, m_szServiceName); + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return TRUE; +} + +BOOL CNTService::Uninstall() +{ + BOOL bResult = FALSE; + + if (!m_bIsWindows9x) + { + // Open the Service Control Manager + SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (!hSCM) + return FALSE; + + SC_HANDLE hService = OpenService(hSCM, m_szServiceName, DELETE); + if (hService) + { + if (DeleteService(hService)) + { + LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_REMOVED, m_szServiceName); + bResult = TRUE; + } + else LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_NOTREMOVED, m_szServiceName); + + CloseServiceHandle(hService); + } + + CloseServiceHandle(hSCM); + } + + return bResult; +} + +/////////////////////////////////////////////////////////////////////////////////////// +// Logging functions + +// This function makes an entry into the application event log +void CNTService::LogEvent(WORD wType, DWORD dwID, const char* pszS1, const char* pszS2, const char* pszS3) +{ + const char* ps[3]; + int iStr = 0; + + if (!m_bIsWindows9x) + { + ps[0] = pszS1; + ps[1] = pszS2; + ps[2] = pszS3; + + for (int i = 0; i < 3; i++) + if (ps[i] != NULL) + iStr++; + + // Check the event source has been registered and if + // not then register it now + if (!m_hEventSource) + m_hEventSource = RegisterEventSource(NULL, m_szServiceName); + + if (m_hEventSource) + ReportEvent(m_hEventSource, wType, 0, dwID, NULL, iStr, 0, ps, NULL); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// +// Service startup and registration + +BOOL CNTService::StartService() +{ + SERVICE_TABLE_ENTRY st[] = + { + { m_szServiceName, ServiceMain }, + { NULL, NULL } + }; + + // There is no need to start the service on Windows 9x. + if (m_bIsWindows9x) + { + ServiceMain(0, NULL); + return TRUE; + } + + BOOL bSuccess = StartServiceCtrlDispatcher(st); + DWORD dwError = GetLastError(); + DebugMsg("Returned from StartServiceCtrlDispatcher() with bSuccess=%d,dwError=%ld", bSuccess, dwError); + return bSuccess; +} + +// static member function (callback) +void CNTService::ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) +{ + // Get a pointer to the C++ object + CNTService* pService = m_pThis; + + pService->DebugMsg("Entering CNTService::ServiceMain()"); + + // Register the control request handler if we're not on Windows 9x. + if (!pService->m_bIsWindows9x) + { + pService->m_Status.dwCurrentState = SERVICE_START_PENDING; + pService->m_hServiceStatus = RegisterServiceCtrlHandler(pService->m_szServiceName, Handler); + if (pService->m_hServiceStatus == NULL) + { + pService->LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_CTRLHANDLERNOTINSTALLED); + return; + } + } + + // Start the initialization + if (pService->Initialize()) + { + pService->m_bIsRunning = TRUE; + pService->m_Status.dwWin32ExitCode = 0; + pService->m_Status.dwCheckPoint = 0; + pService->m_Status.dwWaitHint = 0; + + pService->Run(); + } + + // Tell the service manager we are stopped + pService->SetStatus(SERVICE_STOPPED); + pService->DebugMsg("Leaving CNTService::ServiceMain()"); +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// status functions + +void CNTService::SetStatus(DWORD dwState) +{ + static DWORD dwCheckPoint = 1; + + if (!m_bIsWindows9x) + { + if (m_Status.dwCurrentState == dwState) + m_Status.dwCheckPoint = dwCheckPoint++; + + m_Status.dwCurrentState = dwState; + SetServiceStatus(m_hServiceStatus, &m_Status); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// Service initialization + +BOOL CNTService::Initialize() +{ + DebugMsg("Entering CNTService::Initialize()"); + + // Start the initialization + SetStatus(SERVICE_START_PENDING); + + // Perform the actual initialization + BOOL bResult = OnInit(); + + // Set final state + m_Status.dwWin32ExitCode = GetLastError(); + m_Status.dwCheckPoint = 0; + m_Status.dwWaitHint = 0; + if (!bResult) + { + LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_FAILEDINIT); + SetStatus(SERVICE_STOPPED); + return FALSE; + } + + LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_STARTED); + SetStatus(SERVICE_RUNNING); + + DebugMsg("Leaving CNTService::Initialize()"); + return TRUE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +// main function to do the real work of the service + +// This function performs the main work of the service. +// When this function returns the service has stopped. +BOOL CNTService::Run() +{ + DebugMsg("Entering CNTService::Run()"); + + while (m_bIsRunning) + { + DebugMsg("Sleeping..."); + Sleep(5000); + } + + DebugMsg("Leaving CNTService::Run()"); + return FALSE; +} + +////////////////////////////////////////////////////////////////////////////////////// +// Control request handlers + +// static member function (callback) to handle commands from the +// service control manager +void CNTService::Handler(DWORD dwOpcode) +{ + // Get a pointer to the object + CNTService* pService = m_pThis; + + switch (dwOpcode) + { + case SERVICE_CONTROL_STOP: + pService->SetStatus(SERVICE_STOP_PENDING); + pService->m_bIsRunning = FALSE; + pService->OnStop(); + pService->SetStatus(SERVICE_STOPPED); + pService->LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_STOPPED); + break; + + case SERVICE_CONTROL_PAUSE: + pService->SetStatus(SERVICE_PAUSE_PENDING); + pService->OnPause(); + pService->SetStatus(SERVICE_PAUSED); + break; + + case SERVICE_CONTROL_CONTINUE: + pService->SetStatus(SERVICE_CONTINUE_PENDING); + pService->OnContinue(); + pService->SetStatus(SERVICE_RUNNING); + break; + + case SERVICE_CONTROL_INTERROGATE: + pService->OnInterrogate(); + break; + + case SERVICE_CONTROL_SHUTDOWN: + pService->OnShutdown(); + break; + + default: + if (dwOpcode >= SERVICE_CONTROL_USER) + { + if (!pService->OnUserControl(dwOpcode)) + pService->LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_BADREQUEST); + } + else pService->LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_BADREQUEST); + break; + } + + // Report current status + SetServiceStatus(pService->m_hServiceStatus, &pService->m_Status); +} + +// Called when the service is first initialized +BOOL CNTService::OnInit() +{ + DebugMsg("CNTService::OnInit()"); + return TRUE; +} + +// Called when the service control manager wants to stop the service +void CNTService::OnStop() +{ + DebugMsg("CNTService::OnStop()"); +} + +// called when the service is interrogated +void CNTService::OnInterrogate() +{ + DebugMsg("CNTService::OnInterrogate()"); +} + +// called when the service is paused +void CNTService::OnPause() +{ + DebugMsg("CNTService::OnPause()"); +} + +// called when the service is continued +void CNTService::OnContinue() +{ + DebugMsg("CNTService::OnContinue()"); +} + +// called when the service is shut down +void CNTService::OnShutdown() +{ + DebugMsg("CNTService::OnShutdown()"); +} + +// called when the service gets a user control message +BOOL CNTService::OnUserControl(DWORD dwOpcode) +{ + DebugMsg("CNTService::OnUserControl(%8.8lXH)", dwOpcode); + return FALSE; +} + + +//////////////////////////////////////////////////////////////////////////////////////////// +// Debugging support + +void CNTService::DebugMsg(const char* pszFormat, ...) +{ + char buf[1024]; + sprintf(buf, "[%s](%lu): ", m_szServiceName, GetCurrentThreadId()); + va_list arglist; + va_start(arglist, pszFormat); + vsprintf(&buf[strlen(buf)], pszFormat, arglist); + va_end(arglist); + strcat(buf, "\n"); + OutputDebugString(buf); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.dsp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.dsp new file mode 100644 index 0000000000..f636506a47 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.dsp @@ -0,0 +1,196 @@ +# Microsoft Developer Studio Project File - Name="ntservice" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ntservice - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ntservice.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ntservice.mak" CFG="ntservice - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ntservice - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ntservice - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ntservice - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\WinRel" +# PROP BASE Intermediate_Dir ".\WinRel" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\WinRel" +# PROP Intermediate_Dir ".\WinRel" +# PROP Ignore_Export_Lib 0 +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /YX /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib advapi32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /out:".\WinRel\BeServed.exe" +# SUBTRACT LINK32 /profile /map /debug /nodefaultlib + +!ELSEIF "$(CFG)" == "ntservice - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\WinDebug" +# PROP BASE Intermediate_Dir ".\WinDebug" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\WinDebug" +# PROP Intermediate_Dir ".\WinDebug" +# PROP Ignore_Export_Lib 0 +# ADD BASE CPP /nologo /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /YX /c +# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib advapi32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:".\WinDebug/BeServed.exe" +# SUBTRACT LINK32 /map /nodefaultlib + +!ENDIF + +# Begin Target + +# Name "ntservice - Win32 Release" +# Name "ntservice - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\authentication.cpp +# End Source File +# Begin Source File + +SOURCE=.\BeServed.cpp +# End Source File +# Begin Source File + +SOURCE=.\BlowFish.cpp +# End Source File +# Begin Source File + +SOURCE=.\myservice.cpp +# End Source File +# Begin Source File + +SOURCE=.\NTServApp.cpp +# End Source File +# Begin Source File + +SOURCE=.\NTServApp.rc +# End Source File +# Begin Source File + +SOURCE=.\NTService.cpp +# End Source File +# Begin Source File + +SOURCE=.\NTServMsg.mc +# End Source File +# Begin Source File + +SOURCE=.\printing.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\authentication.h +# End Source File +# Begin Source File + +SOURCE=.\beCompat.h +# End Source File +# Begin Source File + +SOURCE=.\betalk.h +# End Source File +# Begin Source File + +SOURCE=.\BlowFish.h +# End Source File +# Begin Source File + +SOURCE=.\BlowFishTable.h +# End Source File +# Begin Source File + +SOURCE=.\myservice.h +# End Source File +# Begin Source File + +SOURCE=.\NTServApp.h +# End Source File +# Begin Source File + +SOURCE=.\NTService.h +# End Source File +# Begin Source File + +SOURCE=.\ntservmsg.h +# End Source File +# Begin Source File + +SOURCE=.\printing.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\stdafx.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\icon1.ico +# End Source File +# Begin Source File + +SOURCE=.\MSG00001.bin +# End Source File +# End Group +# Begin Source File + +SOURCE=.\ntservmsg.rc +# PROP BASE Exclude_From_Build 1 +# PROP Exclude_From_Build 1 +# End Source File +# End Target +# End Project diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.dsw b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.dsw new file mode 100644 index 0000000000..dd42a7666c --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "ntservice"=.\ntservice.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.h new file mode 100644 index 0000000000..c0ae7d8cd2 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.h @@ -0,0 +1,57 @@ +// ntservice.h +// +// Definitions for CNTService +// + +#ifndef _NTSERVICE_H_ +#define _NTSERVICE_H_ + +#include "ntservmsg.h" + +#define SERVICE_CONTROL_USER 128 + +class CNTService +{ +public: + CNTService(LPCTSTR pServiceName, LPCTSTR pDisplayName); + virtual ~CNTService(); + + BOOL ParseStandardArgs(int argc, char* argv[]); + BOOL IsInstalled(); + BOOL Install(); + BOOL Uninstall(); + void LogEvent(WORD wType, DWORD dwID, const char* pszS1 = NULL, const char* pszS2 = NULL, const char* pszS3 = NULL); + BOOL StartService(); + void SetStatus(DWORD dwState); + BOOL Initialize(); + virtual BOOL Run(); + virtual BOOL OnInit(); + virtual void OnStop(); + virtual void OnInterrogate(); + virtual void OnPause(); + virtual void OnContinue(); + virtual void OnShutdown(); + virtual BOOL OnUserControl(DWORD dwOpcode); + void DebugMsg(const char* pszFormat, ...); + + // static member functions + static void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv); + static void WINAPI Handler(DWORD dwOpcode); + + // data members + char m_szServiceName[64]; + char m_szDisplayName[64]; + SERVICE_STATUS_HANDLE m_hServiceStatus; + SERVICE_STATUS m_Status; + BOOL m_bIsRunning; + + // This static data is used to obtain the object pointer, but unfortunately limits + // this implementation to one CNTService class per executable. + static CNTService* m_pThis; + +private: + HANDLE m_hEventSource; + BOOL m_bIsWindows9x; +}; + +#endif // _NTSERVICE_H_ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.mak b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.mak new file mode 100644 index 0000000000..0528f226e0 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.mak @@ -0,0 +1,306 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.10 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +!IF "$(CFG)" == "" +CFG=ntservice - Win32 Debug +!MESSAGE No configuration specified. Defaulting to ntservice - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "ntservice - Win32 Release" && "$(CFG)" !=\ + "ntservice - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ntservice.mak" CFG="ntservice - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ntservice - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ntservice - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "ntservice - Win32 Debug" +RSC=rc.exe +CPP=cl.exe + +!IF "$(CFG)" == "ntservice - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "WinRel" +# PROP BASE Intermediate_Dir "WinRel" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinRel" +# PROP Intermediate_Dir "WinRel" +OUTDIR=.\WinRel +INTDIR=.\WinRel + +ALL : ".\WinDebug\ntservice.exe" + +CLEAN : + -@erase "$(INTDIR)\CCLIENT.OBJ" + -@erase "$(INTDIR)\cgiapp.obj" + -@erase "$(INTDIR)\CLISTEN.OBJ" + -@erase "$(INTDIR)\FTPClient.obj" + -@erase "$(INTDIR)\myservice.obj" + -@erase "$(INTDIR)\NTServApp.obj" + -@erase "$(INTDIR)\NTServApp.res" + -@erase "$(INTDIR)\NTService.obj" + -@erase "$(INTDIR)\SERVICE.OBJ" + -@erase "$(INTDIR)\SimpleSocket.obj" + -@erase ".\WinDebug\ntservice.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +.\WinRel\NTService.bsc : $(OUTDIR) $(BSC32_SBRS) +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /YX /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /YX /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE"\ + /Fp"$(INTDIR)/ntservice.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\WinRel/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/NTServApp.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/ntservice.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /profile /machine:I386 /out:"WinDebug/ntservice.exe" +# SUBTRACT LINK32 /map /debug /nodefaultlib +LINK32_FLAGS=kernel32.lib user32.lib\ + advapi32.lib ole32.lib oleaut32.lib uuid.lib\ + ws2_32.lib /nologo /subsystem:console /profile\ + /machine:I386 /out:"WinDebug/ntservice.exe" +LINK32_OBJS= \ + "$(INTDIR)\myservice.obj" \ + "$(INTDIR)\NTServApp.obj" \ + "$(INTDIR)\NTServApp.res" \ + "$(INTDIR)\NTService.obj" + +".\WinDebug\ntservice.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ntservice - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "WinDebug" +# PROP BASE Intermediate_Dir "WinDebug" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WinDebug" +# PROP Intermediate_Dir "WinDebug" +OUTDIR=.\WinDebug +INTDIR=.\WinDebug + +ALL : "$(OUTDIR)\ntservice.exe" + +CLEAN : + -@erase "$(INTDIR)\CCLIENT.OBJ" + -@erase "$(INTDIR)\cgiapp.obj" + -@erase "$(INTDIR)\CLISTEN.OBJ" + -@erase "$(INTDIR)\FTPClient.obj" + -@erase "$(INTDIR)\myservice.obj" + -@erase "$(INTDIR)\NTServApp.obj" + -@erase "$(INTDIR)\NTServApp.res" + -@erase "$(INTDIR)\NTService.obj" + -@erase "$(INTDIR)\SERVICE.OBJ" + -@erase "$(INTDIR)\SimpleSocket.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\ntservice.exe" + -@erase "$(OUTDIR)\ntservice.ilk" + -@erase "$(OUTDIR)\ntservice.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +.\WinDebug\NTService.bsc : $(OUTDIR) $(BSC32_SBRS) +# ADD BASE CPP /nologo /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /YX /c +# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /O2 /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /YX /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MT /W3 /Gm /GX /Zi /O2 /D "_DEBUG" /D "WIN32" /D "_CONSOLE"\ + /Fp"$(INTDIR)/ntservice.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\WinDebug/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/NTServApp.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/ntservice.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 +# SUBTRACT LINK32 /map /nodefaultlib +LINK32_FLAGS=kernel32.lib user32.lib \ + advapi32.lib ole32.lib oleaut32.lib uuid.lib \ + ws2_32.lib /nologo /subsystem:console /incremental:yes\ + /pdb:"$(OUTDIR)/ntservice.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)/ntservice.exe" +LINK32_OBJS= \ + "$(INTDIR)\myservice.obj" \ + "$(INTDIR)\NTServApp.obj" \ + "$(INTDIR)\NTServApp.res" \ + "$(INTDIR)\NTService.obj" + +"$(OUTDIR)\ntservice.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Target + +# Name "ntservice - Win32 Release" +# Name "ntservice - Win32 Debug" + +!IF "$(CFG)" == "ntservice - Win32 Release" + +!ELSEIF "$(CFG)" == "ntservice - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\NTService.cpp +DEP_CPP_NTSER=\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\stdafx.h"\ + + +"$(INTDIR)\NTService.obj" : $(SOURCE) $(DEP_CPP_NTSER) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\NTServApp.cpp +DEP_CPP_NTSERV=\ + ".\logger.h"\ + ".\myservice.h"\ + ".\NTServApp.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\stdafx.h"\ + + +"$(INTDIR)\NTServApp.obj" : $(SOURCE) $(DEP_CPP_NTSERV) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\NTServApp.rc +DEP_RSC_NTSERVA=\ + ".\MSG00001.bin"\ + ".\ntservmsg.rc"\ + + +"$(INTDIR)\NTServApp.res" : $(SOURCE) $(DEP_RSC_NTSERVA) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\NTServMsg.mc + +!IF "$(CFG)" == "ntservice - Win32 Release" + +!ELSEIF "$(CFG)" == "ntservice - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\myservice.cpp + +!IF "$(CFG)" == "ntservice - Win32 Release" + +DEP_CPP_MYSER=\ + ".\myservice.h"\ + ".\NTServApp.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\stdafx.h"\ + {$(INCLUDE)}"\MSWSOCK.H"\ + {$(INCLUDE)}"\WINSOCK2.H"\ + + +"$(INTDIR)\myservice.obj" : $(SOURCE) $(DEP_CPP_MYSER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ntservice - Win32 Debug" + +DEP_CPP_MYSER=\ + ".\myservice.h"\ + ".\NTServApp.h"\ + ".\NTService.h"\ + ".\ntservmsg.h"\ + ".\stdafx.h"\ + {$(INCLUDE)}"\WINSOCK2.H"\ + + +"$(INTDIR)\myservice.obj" : $(SOURCE) $(DEP_CPP_MYSER) "$(INTDIR)" + + +!ENDIF + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.mdp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.mdp new file mode 100644 index 0000000000..3bc3415c52 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.mdp differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.plg b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.plg new file mode 100644 index 0000000000..55032276bc --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.plg @@ -0,0 +1,45 @@ + + +
+

Build Log

+

+--------------------Configuration: ntservice - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "E:\DOCUME~1\KMUSIC~1.USS\LOCALS~1\Temp\RSP76.tmp" with contents +[ +/nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /Fp".\WinRel/ntservice.pch" /YX /Fo".\WinRel/" /Fd".\WinRel/" /FD /c +"E:\Development\Projects\Teldar\BeServed\BeServed.cpp" +] +Creating command line "cl.exe @E:\DOCUME~1\KMUSIC~1.USS\LOCALS~1\Temp\RSP76.tmp" +Creating temporary file "E:\DOCUME~1\KMUSIC~1.USS\LOCALS~1\Temp\RSP77.tmp" with contents +[ +ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:".\WinRel/BeServed.pdb" /machine:I386 /out:".\WinRel\BeServed.exe" +.\WinRel\authentication.obj +.\WinRel\BeServed.obj +.\WinRel\BlowFish.obj +.\WinRel\myservice.obj +.\WinRel\NTServApp.obj +.\WinRel\NTService.obj +.\WinRel\printing.obj +.\WinRel\NTServApp.res +] +Creating command line "link.exe @E:\DOCUME~1\KMUSIC~1.USS\LOCALS~1\Temp\RSP77.tmp" +

Output Window

+Compiling... +BeServed.cpp +E:\Development\Projects\Teldar\BeServed\BeServed.cpp(493) : warning C4018: '>=' : signed/unsigned mismatch +E:\Development\Projects\Teldar\BeServed\BeServed.cpp(511) : warning C4018: '>=' : signed/unsigned mismatch +E:\Development\Projects\Teldar\BeServed\BeServed.cpp(1471) : warning C4018: '<' : signed/unsigned mismatch +E:\Development\Projects\Teldar\BeServed\BeServed.cpp(1554) : warning C4018: '<' : signed/unsigned mismatch +Linking... +LINK : warning LNK4089: all references to "SHELL32.dll" discarded by /OPT:REF +LINK : warning LNK4089: all references to "comdlg32.dll" discarded by /OPT:REF + + + +

Results

+BeServed.exe - 0 error(s), 6 warning(s) +
+ + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.sln b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.sln new file mode 100644 index 0000000000..623a176f1b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ntservice", "ntservice.vcproj", "{51D2F8FD-A2E2-4749-9B09-D0D783638DBE}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = Debug + ConfigName.1 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {51D2F8FD-A2E2-4749-9B09-D0D783638DBE}.Debug.ActiveCfg = Debug|Win32 + {51D2F8FD-A2E2-4749-9B09-D0D783638DBE}.Debug.Build.0 = Debug|Win32 + {51D2F8FD-A2E2-4749-9B09-D0D783638DBE}.Release.ActiveCfg = Release|Win32 + {51D2F8FD-A2E2-4749-9B09-D0D783638DBE}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.suo b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.suo new file mode 100644 index 0000000000..79e20a5c07 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.suo differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.vcp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.vcp new file mode 100644 index 0000000000..aa7a424c2c Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.vcp differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.vcproj b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.vcproj new file mode 100644 index 0000000000..52ed3290ba --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservice.vcproj @@ -0,0 +1,246 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservmsg.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservmsg.h new file mode 100644 index 0000000000..790f04751c --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservmsg.h @@ -0,0 +1,153 @@ +// +// Values are 32 bit values layed out as follows: +// +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---+-+-+-----------------------+-------------------------------+ +// |Sev|C|R| Facility | Code | +// +---+-+-+-----------------------+-------------------------------+ +// +// where +// +// Sev - is the severity code +// +// 00 - Success +// 01 - Informational +// 10 - Warning +// 11 - Error +// +// C - is the Customer code flag +// +// R - is a reserved bit +// +// Facility - is the facility code +// +// Code - is the facility's status code +// +// +// Define the facility codes +// + + +// +// Define the severity codes +// + + +// +// MessageId: EVMSG_INSTALLED +// +// MessageText: +// +// The %1 service was installed. +// +#define EVMSG_INSTALLED 0x00000064L + +// +// MessageId: EVMSG_REMOVED +// +// MessageText: +// +// The %1 service was removed. +// +#define EVMSG_REMOVED 0x00000065L + +// +// MessageId: EVMSG_NOTREMOVED +// +// MessageText: +// +// The %1 service could not be removed. +// +#define EVMSG_NOTREMOVED 0x00000066L + +// +// MessageId: EVMSG_CTRLHANDLERNOTINSTALLED +// +// MessageText: +// +// The control handler could not be installed. +// +#define EVMSG_CTRLHANDLERNOTINSTALLED 0x00000067L + +// +// MessageId: EVMSG_FAILEDINIT +// +// MessageText: +// +// The initialization process failed. +// +#define EVMSG_FAILEDINIT 0x00000068L + +// +// MessageId: EVMSG_STARTED +// +// MessageText: +// +// The service was started. +// +#define EVMSG_STARTED 0x00000069L + +// +// MessageId: EVMSG_BADREQUEST +// +// MessageText: +// +// The service received an unsupported request. +// +#define EVMSG_BADREQUEST 0x0000006AL + +// +// MessageId: EVMSG_DEBUG +// +// MessageText: +// +// Debug: %1 +// +#define EVMSG_DEBUG 0x0000006BL + +// +// MessageId: EVMSG_STOPPED +// +// MessageText: +// +// The service was stopped. +// +#define EVMSG_STOPPED 0x0000006CL + +// +// MessageId: EVMSG_INVALID_SHARE_PATH +// +// MessageText: +// +// The path '%1' could not be resolved and is therefore not exported. +// +#define EVMSG_INVALID_SHARE_PATH 0x0000006DL + +// +// MessageId: EVMSG_SOCKET_INIT_FAILED +// +// MessageText: +// +// The Windows sockets system could not be initialized. +// +#define EVMSG_SOCKET_INIT_FAILED 0x0000006EL + +// +// MessageId: EVMSG_TOO_MANY_SHARES +// +// MessageText: +// +// There are too many shared folders. Shared folder '%1' cannot be exported. +// +#define EVMSG_TOO_MANY_SHARES 0x0000006FL + +// +// MessageId: EVMSG_DUPLICATE_SHARE +// +// MessageText: +// +// The shared folder '%1' is multiply defined. +// +#define EVMSG_DUPLICATE_SHARE 0x00000070L + diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservmsg.mc b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservmsg.mc new file mode 100644 index 0000000000..8162b858e5 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservmsg.mc @@ -0,0 +1,78 @@ + +MessageId=100 +SymbolicName=EVMSG_INSTALLED +Language=English +The %1 service was installed. +. + +MessageId= +SymbolicName=EVMSG_REMOVED +Language=English +The %1 service was removed. +. + +MessageId= +SymbolicName=EVMSG_NOTREMOVED +Language=English +The %1 service could not be removed. +. + +MessageId= +SymbolicName=EVMSG_CTRLHANDLERNOTINSTALLED +Language=English +The control handler could not be installed. +. + +MessageId= +SymbolicName=EVMSG_FAILEDINIT +Language=English +The initialization process failed. +. + +MessageId= +SymbolicName=EVMSG_STARTED +Language=English +The service was started. +. + +MessageId= +SymbolicName=EVMSG_BADREQUEST +Language=English +The service received an unsupported request. +. + +MessageId= +SymbolicName=EVMSG_DEBUG +Language=English +Debug: %1 +. + +MessageId= +SymbolicName=EVMSG_STOPPED +Language=English +The service was stopped. +. + +MessageId= +SymbolicName=EVMSG_INVALID_SHARE_PATH +Language=English +The path '%1' could not be resolved and is therefore not exported. +. + +MessageId= +SymbolicName=EVMSG_SOCKET_INIT_FAILED +Language=English +The Windows sockets system could not be initialized. +. + +MessageId= +SymbolicName=EVMSG_TOO_MANY_SHARES +Language=English +There are too many shared folders. Shared folder '%1' cannot be exported. +. + +MessageId= +SymbolicName=EVMSG_DUPLICATE_SHARE +Language=English +The shared folder '%1' is multiply defined. +. diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservmsg.rc b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservmsg.rc new file mode 100644 index 0000000000..116522b7d4 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ntservmsg.rc @@ -0,0 +1,2 @@ +LANGUAGE 0x9,0x1 +1 11 MSG00001.bin diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/printing.cpp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/printing.cpp new file mode 100644 index 0000000000..7beb3a0454 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/printing.cpp @@ -0,0 +1,287 @@ +#define PRINTDRIVER + +#include "stdafx.h" + +#include "beCompat.h" +#include "betalk.h" +#include "authentication.h" +#include "printing.h" + +#include "string.h" +#include "winspool.h" +#include "stdio.h" + + +extern void btMakePath(char *path, char *dir, char *file); +extern bt_printer *btFindPrinter(char *printerName); + +DWORD WINAPI printerThread(LPVOID data); +void CheckPrintJobStatus(bt_printer *printer, char *printJob); +bool PrintFile(bt_printer *printer, char *jobName, char *filename); + + +// printerThread() +// +DWORD WINAPI printerThread(LPVOID data) +{ + bt_printer *printer = (bt_printer *) data; + struct _finddata_t fileInfo; + char search[B_PATH_NAME_LENGTH], path[B_PATH_NAME_LENGTH]; + long int result, finder; + + if (!data) + return 0; + + // Create the search path for all .job files in the spool folder. + btMakePath(search, printer->spoolDir, "*.job"); + + while (!printer->killed) + { + // Find the first print job. + finder = result = _findfirst(search, &fileInfo); + while (result != -1) + { + // Create the fully-qualified path to this print job file, then check + // its status. + btMakePath(path, printer->spoolDir, fileInfo.name); + CheckPrintJobStatus(printer, path); + + // Get the next print job. + result = _findnext(finder, &fileInfo); + } + + // Close our job search and wait awhile. + _findclose(finder); + Sleep(2000); + } + + return 0; +} + +// CheckPrintJobStatus() +// +void CheckPrintJobStatus(bt_printer *printer, char *printJob) +{ + char dataPath[B_PATH_NAME_LENGTH], dataFile[B_FILE_NAME_LENGTH]; + char jobName[B_FILE_NAME_LENGTH], status[50]; + + GetPrivateProfileString("PrintJob", "Status", "", status, sizeof(status), printJob); + + if (stricmp(status, "Scheduling...") == 0) + { + // Move status from scheduling to printing. + WritePrivateProfileString("PrintJob", "Status", "Printing...", printJob); + + // Get the name of the spooled file and print it. + GetPrivateProfileString("PrintJob", "JobName", "", jobName, sizeof(jobName), printJob); + GetPrivateProfileString("PrintJob", "DataFile", "", dataFile, sizeof(dataFile), printJob); + btMakePath(dataPath, printer->spoolDir, dataFile); + PrintFile(printer, jobName, dataPath); + + // Remove the job and data files. + remove(dataPath); + remove(printJob); + } +} + +// PrintFile() +// +bool PrintFile(bt_printer *printer, char *jobName, char *fileName) +{ + HANDLE hPrinter; + DOC_INFO_1 docInfo; + DWORD dwJob, bytesSent; + size_t bytes; + + // Allocate a buffer for print data. + char *buffer = (char *) malloc(BT_MAX_IO_BUFFER + 1); + if (!buffer) + return false; + + // Open the file for reading + FILE *fp = fopen(fileName, "rb"); + if (!fp) + { + free(buffer); + return false; + } + + // Need a handle to the printer. + if (OpenPrinter(printer->deviceName, &hPrinter, NULL)) + { + // Fill in the structure with info about this "document." + docInfo.pDocName = jobName; + docInfo.pOutputFile = NULL; + docInfo.pDatatype = "RAW"; + + // Inform the spooler the document is beginning. + if ((dwJob = StartDocPrinter(hPrinter, 1, (unsigned char *) &docInfo)) != 0) + { + // Start a page. + if (StartPagePrinter(hPrinter)) + { + // Send the data to the printer. + // Print the file 8K at a time, until we are finished or shut down. + while (!printer->killed) + { + bytes = fread(buffer, 1, BT_MAX_IO_BUFFER, fp); + if (bytes <= 0) + break; + + if (!WritePrinter(hPrinter, buffer, bytes, &bytesSent)) + break; + } + + EndPagePrinter(hPrinter); + } + + EndDocPrinter(hPrinter); + } + + ClosePrinter(hPrinter); + } + + if (ferror(fp)) + clearerr(fp); + + fclose(fp); + free(buffer); + return true; +} + +// btPrintJobNew() +// +int btPrintJobNew(char *printerName, char *user, char *password, int client_s_addr, char *jobName, char *jobId) +{ + char printJob[B_PATH_NAME_LENGTH], dataFile[B_PATH_NAME_LENGTH], addr[40]; + bt_printer *printer = btFindPrinter(printerName); + bt_user_rights *ur; + char *groups[MAX_GROUPS_PER_USER]; + int i, rights; + bool authenticated = false; + + // Create a new print job by writing the .job file and by + // creating the .prn file. + if (printer) + { + SYSTEMTIME st; + int docId = 0; + + // Verify the user has permission to print. + if (printer->security != BT_AUTH_NONE) + { + // Authenticate the user with name/password. + authenticated = authenticateUser(user, password); + if (!authenticated) + return BEOS_EACCES; + + // Does the authenticated user have any rights on this file share? + rights = 0; + for (ur = printer->rights; ur; ur = ur->next) + if (!ur->isGroup && stricmp(ur->user, user) == 0) + rights |= ur->rights; + + // Does the authenticated user belong to any groups that have any rights on this + // file share? + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + groups[i] = NULL; + + getUserGroups(user, groups); + for (ur = printer->rights; ur; ur = ur->next) + if (ur->isGroup) + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + if (groups[i] && stricmp(ur->user, groups[i]) == 0) + { + rights |= ur->rights; + break; + } + + // Free the memory occupied by the group list. + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + if (groups[i]) + free(groups[i]); + + // If no rights have been granted, deny access. + if (!(rights & BT_RIGHTS_PRINT)) + return BEOS_EACCES; + } + + // Create a new job ID. + do + { + GetSystemTime(&st); + sprintf(jobId, "%x-%03d-%d", time(NULL), st.wMilliseconds, docId++); + sprintf(printJob, "%s\\%s.job", printer->spoolDir, jobId); + } while (access(printJob, 0) == 0); + + // Write the job information file. + sprintf(dataFile, "%s.prn", jobId); + WritePrivateProfileString("PrintJob", "JobName", jobName, printJob); + WritePrivateProfileString("PrintJob", "Status", "Queueing...", printJob); + WritePrivateProfileString("PrintJob", "DataFile", dataFile, printJob); + WritePrivateProfileString("PrintJob", "User", user, printJob); + + uint8 *_s_addr = (uint8 *) &client_s_addr; + sprintf(addr, "%d.%d.%d.%d", _s_addr[0], _s_addr[1], _s_addr[2], _s_addr[3]); + WritePrivateProfileString("PrintJob", "Source", addr, printJob); + + // Now create the empty data file. + sprintf(dataFile, "%s\\%s.prn", printer->spoolDir, jobId); +// _creat(dataFile, _S_IWRITE); + HANDLE hFile = CreateFile(dataFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); + CloseHandle(hFile); + + return B_OK; + } + + return BEOS_ENOENT; +} + +// btPrintJobData() +// +int btPrintJobData(char *printerName, char *jobId, char *jobData, int dataLen) +{ + char printJob[B_PATH_NAME_LENGTH]; + bt_printer *printer = btFindPrinter(printerName); + FILE *fp; + + if (printer) + { + sprintf(printJob, "%s\\%s.job", printer->spoolDir, jobId); + if (access(printJob, 0) == 0) + { + sprintf(printJob, "%s\\%s.prn", printer->spoolDir, jobId); + fp = fopen(printJob, "ab"); + if (fp) + { + fwrite(jobData, 1, dataLen, fp); + fclose(fp); + return B_OK; + } + + return BEOS_EACCES; + } + } + + return BEOS_ENOENT; +} + +// btPrintJobCommit() +// +int btPrintJobCommit(char *printerName, char *jobId) +{ + char printJob[B_PATH_NAME_LENGTH]; + bt_printer *printer = btFindPrinter(printerName); + + if (printer) + { + sprintf(printJob, "%s\\%s.job", printer->spoolDir, jobId); + if (access(printJob, 0) == 0) + { + WritePrivateProfileString("PrintJob", "Status", "Scheduling...", printJob); + return B_OK; + } + } + + return BEOS_ENOENT; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/printing.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/printing.h new file mode 100644 index 0000000000..029f5f91ac --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/printing.h @@ -0,0 +1,42 @@ +#include "beCompat.h" +#include "betalk.h" + + +typedef struct +{ + char printerName[MAX_NAME_LENGTH]; + char deviceName[B_FILE_NAME_LENGTH]; + char deviceType[MAX_NAME_LENGTH]; + char spoolDir[B_PATH_NAME_LENGTH]; + + bool killed; + bool used; + + bt_user_rights *rights; + int security; + + HANDLE handlerID; +} bt_printer; + + +typedef struct +{ + char jobName[MAX_DESC_LENGTH + 1]; + uint32 sourceAddr; + char sourceUser[MAX_USERNAME_LENGTH + 1]; + char status[MAX_DESC_LENGTH + 1]; +} bt_print_job; + + +// Although there is no maximum number of entries that can be queued for +// printing, except as limited by available disk space, for simplicity +// BeServed will only report on the first MAX_PRINT_JOBS in the queue. +// This keeps the print job query from requiring repeated calls to handle +// large volume. + +#define MAX_PRINT_JOBS (BT_MAX_IO_BUFFER / sizeof(bt_print_job)) + +int btPrintJobNew(char *printerName, char *user, char *password, int client_s_addr, char *jobName, char *jobId); +int btPrintJobData(char *printerName, char *jobId, char *jobData, int dataLen); +int btPrintJobCommit(char *printerName, char *jobId); +int btPrintJobQuery(char *printerName, bt_print_job *jobList); \ No newline at end of file diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/readerWriter.cpp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/readerWriter.cpp new file mode 100644 index 0000000000..8c433187ed --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/readerWriter.cpp @@ -0,0 +1,110 @@ +// readerWriter.c + +#include "stdafx.h" + +#include "beCompat.h" +#include "betalk.h" +#include "readerWriter.h" + + +bool initManagedData(bt_managed_data *data) +{ + data->readCount = 0; + data->writeCount = 0; + + if (!(data->readCountSem = CreateSemaphore(NULL, 1, 1, NULL))) + return false; + + if (!(data->writeCountSem = CreateSemaphore(NULL, 1, 1, NULL))) + { + CloseHandle(data->readCountSem); + return false; + } + + if (!(data->readerQueue = CreateSemaphore(NULL, 1, 1, NULL))) + { + CloseHandle(data->writeCountSem); + CloseHandle(data->readCountSem); + return false; + } + + if (!(data->reader = CreateSemaphore(NULL, 1, 1, NULL))) + { + CloseHandle(data->readerQueue); + CloseHandle(data->writeCountSem); + CloseHandle(data->readCountSem); + return false; + } + + if (!(data->writer = CreateSemaphore(NULL, 1, 1, NULL))) + { + CloseHandle(data->reader); + CloseHandle(data->readerQueue); + CloseHandle(data->writeCountSem); + CloseHandle(data->readCountSem); + return false; + } + + return true; +} + +void closeManagedData(bt_managed_data *data) +{ + data->readCount = data->writeCount = 0; + + CloseHandle(data->writer); + CloseHandle(data->reader); + CloseHandle(data->readerQueue); + CloseHandle(data->writeCountSem); + CloseHandle(data->readCountSem); +} + +void beginReading(bt_managed_data *data) +{ + WaitForSingleObject(data->readerQueue, INFINITE); + WaitForSingleObject(data->reader, INFINITE); + WaitForSingleObject(data->readCountSem, INFINITE); + + data->readCount++; + if (data->readCount == 1) + WaitForSingleObject(data->writer, INFINITE); + + ReleaseSemaphore(data->readCountSem, 1, NULL); + ReleaseSemaphore(data->reader, 1, NULL); + ReleaseSemaphore(data->readerQueue, 1, NULL); +} + +void endReading(bt_managed_data *data) +{ + WaitForSingleObject(data->readCountSem, INFINITE); + + data->readCount--; + if (data->readCount == 0) + ReleaseSemaphore(data->writer, 1, NULL); + + ReleaseSemaphore(data->readCountSem, 1, NULL); +} + +void beginWriting(bt_managed_data *data) +{ + WaitForSingleObject(data->writeCountSem, INFINITE); + + data->writeCount++; + if (data->writeCount == 1) + WaitForSingleObject(data->reader, INFINITE); + + ReleaseSemaphore(data->writeCountSem, 1, NULL); + WaitForSingleObject(data->writer, INFINITE); +} + +void endWriting(bt_managed_data *data) +{ + ReleaseSemaphore(data->writer, 1, NULL); + WaitForSingleObject(data->writeCountSem, INFINITE); + + data->writeCount--; + if (data->writeCount == 0) + ReleaseSemaphore(data->reader, 1, NULL); + + ReleaseSemaphore(data->writeCountSem, 1, NULL); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/readerWriter.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/readerWriter.h new file mode 100644 index 0000000000..4067767b11 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/readerWriter.h @@ -0,0 +1,37 @@ +// readerWriter.h + +#ifndef _READERWRITER_H_ +#define _READERWRITER_H_ + +#include "beCompat.h" +#include "betalk.h" + +typedef struct managedData +{ + int32 readCount; + int32 writeCount; + + // These two semaphores control access to the readCount and writeCount + // variables. + sem_id readCountSem; + sem_id writeCountSem; + + // The first process wishes to gain read access blocks on the reader + // semaphore, but all other block on the readerQueue, so that writers + // can effectively jump the queue. + sem_id readerQueue; + + // Semaphores for holding waiting processes. + sem_id reader; + sem_id writer; +} bt_managed_data; + + +bool initManagedData(bt_managed_data *data); +void closeManagedData(bt_managed_data *data); +void beginReading(bt_managed_data *data); +void endReading(bt_managed_data *data); +void beginWriting(bt_managed_data *data); +void endWriting(bt_managed_data *data); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/resource.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/resource.h new file mode 100644 index 0000000000..cb9e8ee833 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/resource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by NTServApp.rc +// +#define IDI_ICON1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_AVLtree.cpp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_AVLtree.cpp new file mode 100644 index 0000000000..dd40b309e4 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_AVLtree.cpp @@ -0,0 +1,596 @@ +/* ========================================================================== ** + * ubi_AVLtree.c + * + * Copyright (C) 1991-1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module provides an implementation of AVL height balanced binary + * trees. (Adelson-Velskii, Landis 1962) + * + * This file implements the core of the height-balanced (AVL) tree management + * routines. The header file, ubi_AVLtree.h, contains function prototypes + * for all "exported" functions. + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_AVLtree.c,v $ + * Revision 4.5 2000/01/31 05:21:17 crh + * Made checks for NULL more explicit in a few places. + * + * Revision 4.4 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 4.3 1998/06/03 17:41:16 crh + * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is + * included by all of the binary tree files. + * + * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in + * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping + * of tree types by simply changing a header. Unfortunately, the + * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will + * conflict if used together. You must either choose a single tree + * type, or use the underlying function calls directly. Compare + * the two header files for more information. + * + * Revision 4.2 1998/06/02 01:26:53 crh + * Changed ubi_null.h to sys_include.h to make it more generic. + * + * Revision 4.1 1998/05/20 04:35:50 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 4.0 1998/03/10 03:37:09 crh + * Major changes. + * By adding the AVL balance field to the base ubi_btNode structure, I no + * longer need AVL-specific ReplaceNode(), SwapNodes(), and InitNode() + * functions. The Remove() function is also simplified. It's all much + * cleaner. + * This is rev. 4.0. The 3.x series was dropped. + * + * Revision 2.5 1997/12/23 04:00:42 crh + * In this version, all constants & macros defined in the header file have + * the ubi_tr prefix. Also cleaned up anything that gcc complained about + * when run with '-pedantic -fsyntax-only -Wall'. + * + * Revision 2.4 1997/07/26 04:36:20 crh + * Andrew Leppard, aka "Grazgur", discovered that I still had my brains tied + * on backwards with respect to node deletion. I did some more digging and + * discovered that I was not changing the balance values correctly in the + * single rotation functions. Double rotation was working correctly because + * the formula for changing the balance values is the same for insertion or + * deletion. Not so for single rotation. + * + * I have tested the fix by loading the tree with over 44 thousand names, + * deleting 2,629 of them (all those in which the second character is 'u') + * and then walking the tree recursively to verify that the balance factor of + * each node is correct. Passed. + * + * Thanks Andrew! + * + * Also: + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + Rewrote the ubi_tr macros because they weren't doing what I'd + * hoped they would do (see the bottom of the header file). They work now. + * + * Revision 2.3 1997/06/03 04:41:35 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.2 1995/10/03 22:16:01 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:45:59 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/03/05 14:10:51 CRH + * This revision of ubi_AVLtree coincides with revision 2.0 of ubi_BinTree, + * and so includes all of the changes to that module. In addition, a bug in + * the node deletion process has been fixed. + * + * After rewriting the Locate() function in ubi_BinTree, I decided that it was + * time to overhaul this module. In the process, I discovered a bug related + * to node deletion. To fix the bug, I wrote function Debalance(). A quick + * glance will show that it is very similar to the Rebalance() function. In + * previous versions of this module, I tried to include the functionality of + * Debalance() within Rebalance(), with poor results. + * + * Revision 1.0 93/10/15 22:58:56 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_SplayTree, the locate function was + * called "ubi_sptLocate", but the next and previous functions remained + * "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - May, 1990 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================= ** + */ + +#include "stdafx.h" + +#include "ubi_AVLtree.h" /* Header for THIS module. */ + +/* ========================================================================== ** + * Static data. + */ + +static char ModuleID[] = "ubi_AVLtree\n\ +\t$Revision: 4.5 $\n\ +\t$Date: 2000/01/31 05:21:17 $\n\ +\t$Author: crh $\n"; + +/* ========================================================================== ** + * The next set of functions are the AVL balancing routines. There are left + * and right, single and double rotations. The rotation routines handle the + * rotations and reconnect all tree pointers that might get confused by the + * rotations. A pointer to the new subtree root node is returned. + * + * Note that L1 and R1 are identical, except that all the RIGHTs and LEFTs + * are reversed. The same is true for L2 and R2. I'm sure that there is + * a clever way to reduce the amount of code by combining these functions, + * but it might involve additional overhead, and it would probably be a pain + * to read, debug, etc. + * -------------------------------------------------------------------------- ** + */ + +static ubi_btNodePtr L1( ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Single rotate left. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr tmp; + + tmp = p->Link[ubi_trRIGHT]; + p->Link[ubi_trRIGHT] = tmp->Link[ubi_trLEFT]; + tmp->Link[ubi_trLEFT] = p; + + tmp->Link[ubi_trPARENT] = p->Link[ubi_trPARENT]; + tmp->gender = p->gender; + if( NULL != tmp->Link[ubi_trPARENT] ) + (tmp->Link[ubi_trPARENT])->Link[(int)(tmp->gender)] = tmp; + p->Link[ubi_trPARENT] = tmp; + p->gender = ubi_trLEFT; + if( NULL != p->Link[ubi_trRIGHT] ) + { + p->Link[ubi_trRIGHT]->Link[ubi_trPARENT] = p; + (p->Link[ubi_trRIGHT])->gender = ubi_trRIGHT; + } + p->balance -= ubi_trNormalize( tmp->balance ); + (tmp->balance)--; + return( tmp ); + } /* L1 */ + +static ubi_btNodePtr R1( ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Single rotate right. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr tmp; + + tmp = p->Link[ubi_trLEFT]; + p->Link[ubi_trLEFT] = tmp->Link[ubi_trRIGHT]; + tmp->Link[ubi_trRIGHT] = p; + + tmp->Link[ubi_trPARENT] = p->Link[ubi_trPARENT]; + tmp->gender = p->gender; + if( NULL != tmp->Link[ubi_trPARENT] ) + (tmp->Link[ubi_trPARENT])->Link[(int)(tmp->gender)] = tmp; + p->Link[ubi_trPARENT] = tmp; + p->gender = ubi_trRIGHT; + if( NULL != p->Link[ubi_trLEFT] ) + { + p->Link[ubi_trLEFT]->Link[ubi_trPARENT] = p; + p->Link[ubi_trLEFT]->gender = ubi_trLEFT; + } + p->balance -= ubi_trNormalize( tmp->balance ); + (tmp->balance)++; + return( tmp ); + } /* R1 */ + +static ubi_btNodePtr L2( ubi_btNodePtr tree ) + /* ------------------------------------------------------------------------ ** + * Double rotate left. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr tmp, newroot; + + tmp = tree->Link[ubi_trRIGHT]; + newroot = tmp->Link[ubi_trLEFT]; + tmp->Link[ubi_trLEFT] = newroot->Link[ubi_trRIGHT]; + newroot->Link[ubi_trRIGHT] = tmp; + tree->Link[ubi_trRIGHT] = newroot->Link[ubi_trLEFT]; + newroot->Link[ubi_trLEFT] = tree; + + newroot->Link[ubi_trPARENT] = tree->Link[ubi_trPARENT]; + newroot->gender = tree->gender; + tree->Link[ubi_trPARENT] = newroot; + tree->gender = ubi_trLEFT; + tmp->Link[ubi_trPARENT] = newroot; + tmp->gender = ubi_trRIGHT; + + if( NULL != tree->Link[ubi_trRIGHT] ) + { + tree->Link[ubi_trRIGHT]->Link[ubi_trPARENT] = tree; + tree->Link[ubi_trRIGHT]->gender = ubi_trRIGHT; + } + if( NULL != tmp->Link[ubi_trLEFT] ) + { + tmp->Link[ubi_trLEFT]->Link[ubi_trPARENT] = tmp; + tmp->Link[ubi_trLEFT]->gender = ubi_trLEFT; + } + if( NULL != newroot->Link[ubi_trPARENT] ) + newroot->Link[ubi_trPARENT]->Link[(int)(newroot->gender)] = newroot; + + switch( newroot->balance ) + { + case ubi_trLEFT : + tree->balance = ubi_trEQUAL; tmp->balance = ubi_trRIGHT; break; + case ubi_trEQUAL: + tree->balance = ubi_trEQUAL; tmp->balance = ubi_trEQUAL; break; + case ubi_trRIGHT: + tree->balance = ubi_trLEFT; tmp->balance = ubi_trEQUAL; break; + } + newroot->balance = ubi_trEQUAL; + return( newroot ); + } /* L2 */ + +static ubi_btNodePtr R2( ubi_btNodePtr tree ) + /* ------------------------------------------------------------------------ ** + * Double rotate right. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr tmp, newroot; + + tmp = tree->Link[ubi_trLEFT]; + newroot = tmp->Link[ubi_trRIGHT]; + tmp->Link[ubi_trRIGHT] = newroot->Link[ubi_trLEFT]; + newroot->Link[ubi_trLEFT] = tmp; + tree->Link[ubi_trLEFT] = newroot->Link[ubi_trRIGHT]; + newroot->Link[ubi_trRIGHT] = tree; + + newroot->Link[ubi_trPARENT] = tree->Link[ubi_trPARENT]; + newroot->gender = tree->gender; + tree->Link[ubi_trPARENT] = newroot; + tree->gender = ubi_trRIGHT; + tmp->Link[ubi_trPARENT] = newroot; + tmp->gender = ubi_trLEFT; + + if( NULL != tree->Link[ubi_trLEFT] ) + { + tree->Link[ubi_trLEFT]->Link[ubi_trPARENT] = tree; + tree->Link[ubi_trLEFT]->gender = ubi_trLEFT; + } + if( NULL != tmp->Link[ubi_trRIGHT] ) + { + tmp->Link[ubi_trRIGHT]->Link[ubi_trPARENT] = tmp; + tmp->Link[ubi_trRIGHT]->gender = ubi_trRIGHT; + } + if( NULL != newroot->Link[ubi_trPARENT] ) + newroot->Link[ubi_trPARENT]->Link[(int)(newroot->gender)] = newroot; + + switch( newroot->balance ) + { + case ubi_trLEFT : + tree->balance = ubi_trRIGHT; tmp->balance = ubi_trEQUAL; break; + case ubi_trEQUAL : + tree->balance = ubi_trEQUAL; tmp->balance = ubi_trEQUAL; break; + case ubi_trRIGHT : + tree->balance = ubi_trEQUAL; tmp->balance = ubi_trLEFT; break; + } + newroot->balance = ubi_trEQUAL; + return( newroot ); + } /* R2 */ + + +static ubi_btNodePtr Adjust( ubi_btNodePtr p, char LorR ) + /* ------------------------------------------------------------------------ ** + * Adjust the balance value at node *p. If necessary, rotate the subtree + * rooted at p. + * + * Input: p - A pointer to the node to be adjusted. One of the + * subtrees of this node has changed height, so the + * balance value at this node must be adjusted, possibly + * by rotating the tree at this node. + * LorR - Indicates the TALLER subtree. + * + * Output: A pointer to the (possibly new) root node of the subtree. + * + * Notes: This function may be called after a node has been added *or* + * deleted, so LorR indicates the TALLER subtree. + * ------------------------------------------------------------------------ ** + */ + { + if( p->balance != LorR ) + p->balance += ubi_trNormalize(LorR); + else + { + char tallerbal; /* Balance value of the root of the taller subtree of p. */ + + tallerbal = p->Link[(int)LorR]->balance; + if( ( ubi_trEQUAL == tallerbal ) || ( p->balance == tallerbal ) ) + p = ( (ubi_trLEFT==LorR) ? R1(p) : L1(p) ); /* single rotation */ + else + p = ( (ubi_trLEFT==LorR) ? R2(p) : L2(p) ); /* double rotation */ + } + return( p ); + } /* Adjust */ + +static ubi_btNodePtr Rebalance( ubi_btNodePtr Root, + ubi_btNodePtr subtree, + char LorR ) + /* ------------------------------------------------------------------------ ** + * Rebalance the tree following an insertion. + * + * Input: Root - A pointer to the root node of the whole tree. + * subtree - A pointer to the node that has just gained a new + * child. + * LorR - Gender of the child that has just been gained. + * + * Output: A pointer to the (possibly new) root of the AVL tree. + * Rebalancing the tree moves nodes around a bit, so the node + * that *was* the root, may not be the root when we're finished. + * + * Notes: Rebalance() must walk up the tree from where we are (which is + * where the latest change occurred), rebalancing the subtrees + * along the way. The rebalancing operation can stop if the + * change at the current subtree root won't affect the rest of + * the tree. In the case of an addition, if a subtree root's + * balance becomes EQUAL, then we know that the height of that + * subtree has not changed, so we can exit. + * ------------------------------------------------------------------------ ** + */ + { + while( subtree ) + { + subtree = Adjust( subtree, LorR ); + if( ubi_trPARENT == subtree->gender ) + return( subtree ); + if( ubi_trEQUAL == subtree->balance ) + return( Root ); + LorR = subtree->gender; + subtree = subtree->Link[ubi_trPARENT]; + } + return( Root ); + } /* Rebalance */ + +static ubi_btNodePtr Debalance( ubi_btNodePtr Root, + ubi_btNodePtr subtree, + char LorR ) + /* ------------------------------------------------------------------------ ** + * Rebalance the tree following a deletion. + * + * Input: Root - A pointer to the root node of the whole tree. + * subtree - A pointer to the node who's child has just "left the + * nest". + * LorR - Gender of the child that left. + * + * Output: A pointer to the (possibly new) root of the AVL tree. + * Rebalancing the tree moves nodes around a bit, so the node + * that *was* the root, may not be the root when we're finished. + * + * Notes: Debalance() is subtly different from Rebalance() (above) in + * two respects. + * * When it calls Adjust(), it passes the *opposite* of LorR. + * This is because LorR, as passed into Debalance() indicates + * the shorter subtree. As we move up the tree, LorR is + * assigned the gender of the node that we are leaving (i.e., + * the subtree that we just rebalanced). + * * We know that a subtree has not changed height if the + * balance becomes LEFT or RIGHT. This is the *opposite* of + * what happens in Rebalance(). + * ------------------------------------------------------------------------ ** + */ + { + while( subtree ) + { + subtree = Adjust( subtree, ubi_trRevWay(LorR) ); + if( ubi_trPARENT == subtree->gender ) + return( subtree ); + if( ubi_trEQUAL != subtree->balance ) + return( Root ); + LorR = subtree->gender; + subtree = subtree->Link[ubi_trPARENT]; + } + return( Root ); + } /* Debalance */ + +/* ========================================================================== ** + * Public, exported (ie. not static-ly declared) functions... + * -------------------------------------------------------------------------- ** + */ + +ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ) + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to + * the tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr OtherP; + + if( NULL == OldNode ) + OldNode = &OtherP; + if( ubi_btInsert( RootPtr, + (ubi_btNodePtr)NewNode, + ItemPtr, + (ubi_btNodePtr *)OldNode ) ) + { + if( NULL != *OldNode ) + NewNode->balance = (*OldNode)->balance; + else + { + NewNode->balance = ubi_trEQUAL; + RootPtr->root = (ubi_btNodePtr)Rebalance( (ubi_btNodePtr)RootPtr->root, + NewNode->Link[ubi_trPARENT], + NewNode->gender ); + } + return( ubi_trTRUE ); + } + return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ + } /* ubi_avlInsert */ + +ubi_btNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr, + ubi_btNodePtr DeadNode ) + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree, after which the + * tree is rebalanced. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * + * ------------------------------------------------------------------------ ** + */ + { + /* Let the base binary tree module do the removal, then rebalance. */ + if( NULL != ubi_btRemove( RootPtr, DeadNode ) ) + RootPtr->root = Debalance( RootPtr->root, + DeadNode->Link[ubi_trPARENT], + DeadNode->gender ); + return( DeadNode ); + } /* ubi_avlRemove */ + +int ubi_avlModuleID( int size, char *list[] ) + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array . + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of that were used. If this value + * is less than , the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + { + if( size > 0 ) + { + list[0] = ModuleID; + if( size > 1 ) + return( 1 + ubi_btModuleID( --size, &(list[1]) ) ); + return( 1 ); + } + return( 0 ); + } /* ubi_avlModuleID */ + +/* ============================== The End ============================== */ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_AVLtree.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_AVLtree.h new file mode 100644 index 0000000000..040ce41984 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_AVLtree.h @@ -0,0 +1,274 @@ +#ifndef UBI_AVLTREE_H +#define UBI_AVLTREE_H +/* ========================================================================== ** + * ubi_AVLtree.h + * + * Copyright (C) 1991-1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module provides an implementation of AVL height balanced binary + * trees. (Adelson-Velskii, Landis 1962) + * + * This header file contains the basic AVL structure and pointer typedefs + * as well as the prototypes needed to access the functions in the AVL + * module ubi_AVLtree. The .c file implements the low-level height balancing + * routines that manage the AVL tree, plus all of the basic primops for + * adding, searching for, and deleting nodes. + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * $Log: ubi_AVLtree.h,v $ + * Revision 4.5 2000/01/31 05:21:17 crh + * Made checks for NULL more explicit in a few places. + * + * Revision 4.4 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 4.3 1998/06/03 17:41:46 crh + * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is + * included by all of the binary tree files. + * + * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in + * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping + * of tree types by simply changing a header. Unfortunately, the + * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will + * conflict if used together. You must either choose a single tree + * type, or use the underlying function calls directly. Compare + * the two header files for more information. + * + * Revision 4.2 1998/06/02 01:26:53 crh + * Changed ubi_null.h to sys_include.h to make it more generic. + * + * Revision 4.1 1998/05/20 04:35:50 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 4.0 1998/03/10 03:34:45 crh + * Major changes. + * By adding the AVL balance field to the base ubi_btNode structure, I no + * longer need AVL-specific ReplaceNode(), SwapNodes(), and InitNode() + * functions. The Remove() function is also simplified. It's all much + * cleaner. + * This is rev. 4.0. The 3.x series was dropped. + * + * Revision 2.5 1997/12/23 04:00:15 crh + * In this version, all constants & macros defined in the header file have + * the ubi_tr prefix. Also cleaned up anything that gcc complained about + * when run with '-pedantic -fsyntax-only -Wall'. + * + * Revision 2.4 1997/07/26 04:36:23 crh + * Andrew Leppard, aka "Grazgur", discovered that I still had my brains tied + * on backwards with respect to node deletion. I did some more digging and + * discovered that I was not changing the balance values correctly in the + * single rotation functions. Double rotation was working correctly because + * the formula for changing the balance values is the same for insertion or + * deletion. Not so for single rotation. + * + * I have tested the fix by loading the tree with over 44 thousand names, + * deleting 2,629 of them (all those in which the second character is 'u') + * and then walking the tree recursively to verify that the balance factor of + * each node is correct. Passed. + * + * Thanks Andrew! + * + * Also: + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + Rewrote the ubi_tr<func> macros because they weren't doing what I'd + * hoped they would do (see the bottom of the header file). They work now. + * + * Revision 2.3 1997/06/03 05:22:07 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.2 1995/10/03 22:15:47 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:46:44 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/03/05 14:11:22 CRH + * This revision of ubi_AVLtree coincides with revision 2.0 of ubi_BinTree, + * and so includes all of the changes to that module. In addition, a bug in + * the node deletion process has been fixed. + * + * After rewriting the Locate() function in ubi_BinTree, I decided that it was + * time to overhaul this module. In the process, I discovered a bug related + * to node deletion. To fix the bug, I wrote function Debalance(). A quick + * glance will show that it is very similar to the Rebalance() function. In + * previous versions of this module, I tried to include the functionality of + * Debalance() within Rebalance(), with poor results. + * + * Revision 1.0 93/10/15 22:58:48 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_SplayTree, the locate function was + * called "ubi_sptLocate", but the next and previous functions remained + * "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - May, 1990 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================= ** + */ + +#include "ubi_BinTree.h" /* Base erg binary tree support. */ + +/* -------------------------------------------------------------------------- ** + * Function prototypes. + * -------------------------------------------------------------------------- ** + */ + +ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ); + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to + * the tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr, + ubi_btNodePtr DeadNode ); + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree, after which the + * tree is rebalanced. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + +int ubi_avlModuleID( int size, char *list[] ); + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- ** + * Masquarade... + * + * This set of defines allows you to write programs that will use any of the + * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). + * Instead of using ubi_avl... or ubi_bt, use ubi_tr... and select the tree + * type by including the appropriate module header. + */ + +#undef ubi_trInsert +#define ubi_trInsert( Rp, Nn, Ip, On ) \ + ubi_avlInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ + (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) + +#undef ubi_trRemove +#define ubi_trRemove( Rp, Dn ) \ + ubi_avlRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) + +#undef ubi_trModuleID +#define ubi_trModuleID( s, l ) ubi_avlModuleID( s, l ) + + +/* =========================== End ubi_AVLtree.h =========================== */ +#endif /* UBI_AVLTREE_H */ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_BinTree.cpp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_BinTree.cpp new file mode 100644 index 0000000000..9f7019ea4e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_BinTree.cpp @@ -0,0 +1,1135 @@ +/* ========================================================================== ** + * ubi_BinTree.c + * + * Copyright (C) 1991-1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements a simple binary tree. + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_BinTree.c,v $ + * Revision 4.10 2000/06/06 20:38:40 crh + * In the ReplaceNode() function, the old node header was being copied + * to the new node header using a byte-by-byte copy. This was causing + * the 'insure' software testing program to report a memory leak. The + * fix was to do a simple assignement: *newnode = *oldnode; + * This quieted the (errant) memory leak reports and is probably a bit + * faster than the bytewise copy. + * + * Revision 4.9 2000/01/08 23:24:30 crh + * Clarified a variety of if( pointer ) lines, replacing them with + * if( NULL != pointer ). This is more correct, and I have heard + * of at least one (obscure?) system out there that uses a non-zero + * value for NULL. + * Also, speed improvement in Neighbor(). It was comparing pointers + * when it could have compared two gender values. The pointer + * comparison was somewhat indirect (does pointer equal the pointer + * of the parent of the node pointed to by pointer). Urq. + * + * Revision 4.8 1999/09/22 03:40:30 crh + * Modified ubi_btTraverse() and ubi_btKillTree(). They now return an + * unsigned long indicating the number of nodes processed. The change + * is subtle. An empty tree formerly returned False, and now returns + * zero. + * + * Revision 4.7 1998/10/21 06:14:42 crh + * Fixed bugs in FirstOf() and LastOf() reported by Massimo Campostrini. + * See function comments. + * + * Revision 4.6 1998/07/25 17:02:10 crh + * Added the ubi_trNewTree() macro. + * + * Revision 4.5 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 4.4 1998/06/03 17:42:46 crh + * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is + * included by all of the binary tree files. + * + * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in + * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping + * of tree types by simply changing a header. Unfortunately, the + * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will + * conflict if used together. You must either choose a single tree + * type, or use the underlying function calls directly. Compare + * the two header files for more information. + * + * Revision 4.3 1998/06/02 01:28:43 crh + * Changed ubi_null.h to sys_include.h to make it more generic. + * + * Revision 4.2 1998/05/20 04:32:36 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * Also, the balance and gender fields of the node were declared as + * signed char. As I understand it, at least one SunOS or Solaris + * compiler doesn't like "signed char". The declarations were + * wrong anyway, so I changed them to simple "char". + * + * Revision 4.1 1998/03/31 06:11:57 crh + * Thomas Aglassinger sent E'mail pointing out errors in the + * dereferencing of function pointers, and a missing typecast. + * Thanks, Thomas! + * + * Revision 4.0 1998/03/10 03:19:22 crh + * Added the AVL field 'balance' to the ubi_btNode structure. This means + * that all BinTree modules now use the same basic node structure, which + * greatly simplifies the AVL module. + * Decided that this was a big enough change to justify a new major revision + * number. 3.0 was an error, so we're at 4.0. + * + * Revision 2.6 1998/01/24 06:27:46 crh + * Added ubi_trCount() macro. + * + * Revision 2.5 1997/12/23 03:56:29 crh + * In this version, all constants & macros defined in the header file have + * the ubi_tr prefix. Also cleaned up anything that gcc complained about + * when run with '-pedantic -fsyntax-only -Wall'. + * + * Revision 2.4 1997/07/26 04:11:10 crh + * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE + * and ubi_trFALSE. + * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. + * + There used to be something called "ubi_TypeDefs.h". I got rid of it. + * + Added function ubi_btLeafNode(). + * + * Revision 2.3 1997/06/03 05:16:17 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. + * Also changed the interface to function InitTree(). See the comments + * for this function for more information. + * + * Revision 2.2 1995/10/03 22:00:07 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:37:10 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:00:17 CRH + * Revision 2.0 of this program includes the following changes: + * + * 1) A fix to a major typo in the RepaceNode() function. + * 2) The addition of the static function Border(). + * 3) The addition of the public functions FirstOf() and LastOf(), which + * use Border(). These functions are used with trees that allow + * duplicate keys. + * 4) A complete rewrite of the Locate() function. Locate() now accepts + * a "comparison" operator. + * 5) Overall enhancements to both code and comments. + * + * I decided to give this a new major rev number because the interface has + * changed. In particular, there are two new functions, and changes to the + * Locate() function. + * + * Revision 1.0 93/10/15 22:44:59 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_SplayTree, the locate function was + * called "ubi_sptLocate", but the next and previous functions remained + * "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================== ** + */ + +#include "stdafx.h" + +#include "ubi_BinTree.h" /* Header for this module. */ + +/* ========================================================================== ** + * Static data. + */ + +static char ModuleID[] = "ubi_BinTree\n\ +\t$Revision: 4.10 $\n\ +\t$Date: 2000/06/06 20:38:40 $\n\ +\t$Author: crh $\n"; + +/* ========================================================================== ** + * Internal (private) functions. + */ + +static ubi_btNodePtr qFind( ubi_btCompFunc cmp, + ubi_btItemPtr FindMe, + register ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for a node + * matching a specific key. It is called "qFind()" because it is + * faster that TreeFind (below). + * + * Input: + * cmp - a pointer to the tree's comparison function. + * FindMe - a pointer to the key value for which to search. + * p - a pointer to the starting point of the search.

+ * is considered to be the root of a subtree, and only + * the subtree will be searched. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. + * ------------------------------------------------------------------------ ** + */ + { + int tmp; + + while( (NULL != p) + && ((tmp = ubi_trAbNormal( (*cmp)(FindMe, p) )) != ubi_trEQUAL) ) + p = p->Link[tmp]; + + return( p ); + } /* qFind */ + +static ubi_btNodePtr TreeFind( ubi_btItemPtr findme, + ubi_btNodePtr p, + ubi_btNodePtr *parentp, + char *gender, + ubi_btCompFunc CmpFunc ) + /* ------------------------------------------------------------------------ ** + * TreeFind() searches a tree for a given value (findme). It will return a + * pointer to the target node, if found, or NULL if the target node was not + * found. + * + * TreeFind() also returns, via parameters, a pointer to the parent of the + * target node, and a LEFT or RIGHT value indicating which child of the + * parent is the target node. *If the target is not found*, then these + * values indicate the place at which the target *should be found*. This + * is useful when inserting a new node into a tree or searching for nodes + * "near" the target node. + * + * The parameters are: + * + * findme - is a pointer to the key information to be searched for. + * p - points to the root of the tree to be searched. + * parentp - will return a pointer to a pointer to the !parent! of the + * target node, which can be especially usefull if the target + * was not found. + * gender - returns LEFT or RIGHT to indicate which child of *parentp + * was last searched. + * CmpFunc - points to the comparison function. + * + * This function is called by ubi_btLocate() and ubi_btInsert(). + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr tmp_p = p; + ubi_btNodePtr tmp_pp = NULL; + char tmp_gender = ubi_trEQUAL; + int tmp_cmp; + + while( (NULL != tmp_p) + && (ubi_trEQUAL != (tmp_cmp = ubi_trAbNormal((*CmpFunc)(findme, tmp_p)))) ) + { + tmp_pp = tmp_p; /* Keep track of previous node. */ + tmp_gender = (char)tmp_cmp; /* Keep track of sex of child. */ + tmp_p = tmp_p->Link[tmp_cmp]; /* Go to child. */ + } + *parentp = tmp_pp; /* Return results. */ + *gender = tmp_gender; + return( tmp_p ); + } /* TreeFind */ + +static void ReplaceNode( ubi_btNodePtr *parent, + ubi_btNodePtr oldnode, + ubi_btNodePtr newnode ) + /* ------------------------------------------------------------------------ ** + * Remove node oldnode from the tree, replacing it with node newnode. + * + * Input: + * parent - A pointer to he parent pointer of the node to be + * replaced. may point to the Link[] field of + * a parent node, or it may indicate the root pointer at + * the top of the tree. + * oldnode - A pointer to the node that is to be replaced. + * newnode - A pointer to the node that is to be installed in the + * place of <*oldnode>. + * + * Notes: Don't forget to free oldnode. + * Also, this function used to have a really nasty typo + * bug. "oldnode" and "newnode" were swapped in the line + * that now reads: + * ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; + * Bleah! + * ------------------------------------------------------------------------ ** + */ + { + *newnode = *oldnode; /* Copy node internals to new node. */ + + (*parent) = newnode; /* Old node's parent points to new child. */ + /* Now tell the children about their new step-parent. */ + if( oldnode->Link[ubi_trLEFT] ) + (oldnode->Link[ubi_trLEFT])->Link[ubi_trPARENT] = newnode; + if( oldnode->Link[ubi_trRIGHT] ) + (oldnode->Link[ubi_trRIGHT])->Link[ubi_trPARENT] = newnode; + } /* ReplaceNode */ + +static void SwapNodes( ubi_btRootPtr RootPtr, + ubi_btNodePtr Node1, + ubi_btNodePtr Node2 ) + /* ------------------------------------------------------------------------ ** + * This function swaps two nodes in the tree. Node1 will take the place of + * Node2, and Node2 will fill in the space left vacant by Node 1. + * + * Input: + * RootPtr - pointer to the tree header structure for this tree. + * Node1 - \ + * > These are the two nodes which are to be swapped. + * Node2 - / + * + * Notes: + * This function does a three step swap, using a dummy node as a place + * holder. This function is used by ubi_btRemove(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr *Parent; + ubi_btNode dummy; + ubi_btNodePtr dummy_p = &dummy; + + /* Replace Node 1 with the dummy, thus removing Node1 from the tree. */ + if( NULL != Node1->Link[ubi_trPARENT] ) + Parent = &((Node1->Link[ubi_trPARENT])->Link[(int)(Node1->gender)]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, Node1, dummy_p ); + + /* Swap Node 1 with Node 2, placing Node 1 back into the tree. */ + if( NULL != Node2->Link[ubi_trPARENT] ) + Parent = &((Node2->Link[ubi_trPARENT])->Link[(int)(Node2->gender)]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, Node2, Node1 ); + + /* Swap Node 2 and the dummy, thus placing Node 2 back into the tree. */ + if( NULL != dummy_p->Link[ubi_trPARENT] ) + Parent = &((dummy_p->Link[ubi_trPARENT])->Link[(int)(dummy_p->gender)]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, dummy_p, Node2 ); + } /* SwapNodes */ + +/* -------------------------------------------------------------------------- ** + * These routines allow you to walk through the tree, forwards or backwards. + */ + +static ubi_btNodePtr SubSlide( register ubi_btNodePtr P, + register int whichway ) + /* ------------------------------------------------------------------------ ** + * Slide down the side of a subtree. + * + * Given a starting node, this function returns a pointer to the LEFT-, or + * RIGHT-most descendent, *or* (if whichway is PARENT) to the tree root. + * + * Input: P - a pointer to a starting place. + * whichway - the direction (LEFT, RIGHT, or PARENT) in which to + * travel. + * Output: A pointer to a node that is either the root, or has no + * whichway-th child but is within the subtree of P. Note that + * the return value may be the same as P. The return value *will + * be* NULL if P is NULL. + * ------------------------------------------------------------------------ ** + */ + { + + if( NULL != P ) + while( NULL != P->Link[ whichway ] ) + P = P->Link[ whichway ]; + return( P ); + } /* SubSlide */ + +static ubi_btNodePtr Neighbor( register ubi_btNodePtr P, + register int whichway ) + /* ------------------------------------------------------------------------ ** + * Given starting point p, return the (key order) next or preceeding node + * in the tree. + * + * Input: P - Pointer to our starting place node. + * whichway - the direction in which to travel to find the + * neighbor, i.e., the RIGHT neighbor or the LEFT + * neighbor. + * + * Output: A pointer to the neighboring node, or NULL if P was NULL. + * + * Notes: If whichway is PARENT, the results are unpredictable. + * ------------------------------------------------------------------------ ** + */ + { + if( P ) + { + if( NULL != P->Link[ whichway ] ) + return( SubSlide( P->Link[ whichway ], (char)ubi_trRevWay(whichway) ) ); + else + while( NULL != P->Link[ ubi_trPARENT ] ) + { + if( whichway == P->gender ) + P = P->Link[ ubi_trPARENT ]; + else + return( P->Link[ ubi_trPARENT ] ); + } + } + return( NULL ); + } /* Neighbor */ + +static ubi_btNodePtr Border( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_btNodePtr p, + int whichway ) + /* ------------------------------------------------------------------------ ** + * Given starting point p, which has a key value equal to *FindMe, locate + * the first (index order) node with the same key value. + * + * This function is useful in trees that have can have duplicate keys. + * For example, consider the following tree: + * Tree Traversal + * 2 If

points to the root and is RIGHT, 3 + * / \ then the return value will be a pointer to the / \ + * 2 2 RIGHT child of the root node. The tree on 2 5 + * / / \ the right shows the order of traversal. / / \ + * 1 2 3 1 4 6 + * + * Input: RootPtr - Pointer to the tree root structure. + * FindMe - Key value for comparisons. + * p - Pointer to the starting-point node. + * whichway - the direction in which to travel to find the + * neighbor, i.e., the RIGHT neighbor or the LEFT + * neighbor. + * + * Output: A pointer to the first (index, or "traversal", order) node with + * a Key value that matches *FindMe. + * + * Notes: If whichway is PARENT, or if the tree does not allow duplicate + * keys, this function will return

. + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr q; + + /* Exit if there's nothing that can be done. */ + if( !ubi_trDups_OK( RootPtr ) || (ubi_trPARENT == whichway) ) + return( p ); + + /* First, if needed, move up the tree. We need to get to the root of the + * subtree that contains all of the matching nodes. + */ + q = p->Link[ubi_trPARENT]; + while( (NULL != q) + && (ubi_trEQUAL == ubi_trAbNormal( (*(RootPtr->cmp))(FindMe, q) )) ) + { + p = q; + q = p->Link[ubi_trPARENT]; + } + + /* Next, move back down in the "whichway" direction. */ + q = p->Link[whichway]; + while( NULL != q ) + { + q = qFind( RootPtr->cmp, FindMe, q ); + if( q ) + { + p = q; + q = p->Link[whichway]; + } + } + return( p ); + } /* Border */ + + +/* ========================================================================== ** + * Exported utilities. + */ + +long ubi_btSgn( register long x ) + /* ------------------------------------------------------------------------ ** + * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. + * + * Input: x - a signed long integer value. + * + * Output: the "sign" of x, represented as follows: + * -1 == negative + * 0 == zero (no sign) + * 1 == positive + * + * Note: This utility is provided in order to facilitate the conversion + * of C comparison function return values into BinTree direction + * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the + * ubi_trAbNormal() conversion macro! + * + * ------------------------------------------------------------------------ ** + */ + { + return( (x)?((x>0)?(1):(-1)):(0) ); + } /* ubi_btSgn */ + +ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: a pointer to a ubi_btNode structure to be initialized. + * Output: a pointer to the initialized ubi_btNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + { + NodePtr->Link[ ubi_trLEFT ] = NULL; + NodePtr->Link[ ubi_trPARENT ] = NULL; + NodePtr->Link[ ubi_trRIGHT ] = NULL; + NodePtr->gender = ubi_trEQUAL; + NodePtr->balance = ubi_trEQUAL; + return( NodePtr ); + } /* ubi_btInitNode */ + +ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, + ubi_btCompFunc CompFunc, + char Flags ) + /* ------------------------------------------------------------------------ ** + * Initialize the fields of a Tree Root header structure. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure to be + * initialized. + * CompFunc - a pointer to a comparison function that will be used + * whenever nodes in the tree must be compared against + * outside values. + * Flags - One bytes worth of flags. Flags include + * ubi_trOVERWRITE and ubi_trDUPKEY. See the header + * file for more info. + * + * Output: a pointer to the initialized ubi_btRoot structure (ie. the + * same value as RootPtr). + * + * Note: The interface to this function has changed from that of + * previous versions. The parameter replaces two + * boolean parameters that had the same basic effect. + * + * ------------------------------------------------------------------------ ** + */ + { + if( RootPtr ) + { + RootPtr->root = NULL; + RootPtr->count = 0L; + RootPtr->cmp = CompFunc; + RootPtr->flags = (Flags & ubi_trDUPKEY) ? ubi_trDUPKEY : Flags; + } /* There are only two supported flags, and they are + * mutually exclusive. ubi_trDUPKEY takes precedence + * over ubi_trOVERWRITE. + */ + return( RootPtr ); + } /* ubi_btInitTree */ + +ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ) + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr OtherP, + parent = NULL; + char tmp; + + if( NULL == OldNode ) /* If they didn't give us a pointer, supply our own. */ + OldNode = &OtherP; + + (void)ubi_btInitNode( NewNode ); /* Init the new node's BinTree fields. */ + + /* Find a place for the new node. */ + *OldNode = TreeFind(ItemPtr, (RootPtr->root), &parent, &tmp, (RootPtr->cmp)); + + /* Now add the node to the tree... */ + if( NULL == (*OldNode) ) /* The easy one: we have a space for a new node! */ + { + if( NULL == parent ) + RootPtr->root = NewNode; + else + { + parent->Link[(int)tmp] = NewNode; + NewNode->Link[ubi_trPARENT] = parent; + NewNode->gender = tmp; + } + (RootPtr->count)++; + return( ubi_trTRUE ); + } + + /* If we reach this point, we know that a duplicate node exists. This + * section adds the node to the tree if duplicate keys are allowed. + */ + if( ubi_trDups_OK(RootPtr) ) /* Key exists, add duplicate */ + { + ubi_btNodePtr q; + + tmp = ubi_trRIGHT; + q = (*OldNode); + *OldNode = NULL; + while( NULL != q ) + { + parent = q; + if( tmp == ubi_trEQUAL ) + tmp = ubi_trRIGHT; + q = q->Link[(int)tmp]; + if ( q ) + tmp = ubi_trAbNormal( (*(RootPtr->cmp))(ItemPtr, q) ); + } + parent->Link[(int)tmp] = NewNode; + NewNode->Link[ubi_trPARENT] = parent; + NewNode->gender = tmp; + (RootPtr->count)++; + return( ubi_trTRUE ); + } + + /* If we get to *this* point, we know that we are not allowed to have + * duplicate nodes, but our node keys match, so... may we replace the + * old one? + */ + if( ubi_trOvwt_OK(RootPtr) ) /* Key exists, we replace */ + { + if( NULL == parent ) + ReplaceNode( &(RootPtr->root), *OldNode, NewNode ); + else + ReplaceNode( &(parent->Link[(int)((*OldNode)->gender)]), + *OldNode, NewNode ); + return( ubi_trTRUE ); + } + + return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ + } /* ubi_btInsert */ + +ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, + ubi_btNodePtr DeadNode ) + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p, + *parentp; + int tmp; + + /* if the node has both left and right subtrees, then we have to swap + * it with another node. The other node we choose will be the Prev()ious + * node, which is garunteed to have no RIGHT child. + */ + if( (NULL != DeadNode->Link[ubi_trLEFT]) + && (NULL != DeadNode->Link[ubi_trRIGHT]) ) + SwapNodes( RootPtr, DeadNode, ubi_btPrev( DeadNode ) ); + + /* The parent of the node to be deleted may be another node, or it may be + * the root of the tree. Since we're not sure, it's best just to have + * a pointer to the parent pointer, whatever it is. + */ + if( NULL == DeadNode->Link[ubi_trPARENT] ) + parentp = &( RootPtr->root ); + else + parentp = &((DeadNode->Link[ubi_trPARENT])->Link[(int)(DeadNode->gender)]); + + /* Now link the parent to the only grand-child and patch up the gender. */ + tmp = ((DeadNode->Link[ubi_trLEFT])?ubi_trLEFT:ubi_trRIGHT); + + p = (DeadNode->Link[tmp]); + if( NULL != p ) + { + p->Link[ubi_trPARENT] = DeadNode->Link[ubi_trPARENT]; + p->gender = DeadNode->gender; + } + (*parentp) = p; + + /* Finished, reduce the node count and return. */ + (RootPtr->count)--; + return( DeadNode ); + } /* ubi_btRemove */ + +ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ) + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr p; + ubi_btNodePtr parent; + char whichkid; + + /* Start by searching for a matching node. */ + p = TreeFind( FindMe, + RootPtr->root, + &parent, + &whichkid, + RootPtr->cmp ); + + if( NULL != p ) /* If we have found a match, we can resolve as follows: */ + { + switch( CompOp ) + { + case ubi_trLT: /* It's just a jump to the left... */ + p = Border( RootPtr, FindMe, p, ubi_trLEFT ); + return( Neighbor( p, ubi_trLEFT ) ); + case ubi_trGT: /* ...and then a jump to the right. */ + p = Border( RootPtr, FindMe, p, ubi_trRIGHT ); + return( Neighbor( p, ubi_trRIGHT ) ); + default: + p = Border( RootPtr, FindMe, p, ubi_trLEFT ); + return( p ); + } + } + + /* Else, no match. */ + if( ubi_trEQ == CompOp ) /* If we were looking for an exact match... */ + return( NULL ); /* ...forget it. */ + + /* We can still return a valid result for GT, GE, LE, and LT. + * points to a node with a value that is either just before or + * just after the target value. + * Remaining possibilities are LT and GT (including LE & GE). + */ + if( (ubi_trLT == CompOp) || (ubi_trLE == CompOp) ) + return( (ubi_trLEFT == whichkid) ? Neighbor( parent, whichkid ) : parent ); + else + return( (ubi_trRIGHT == whichkid) ? Neighbor( parent, whichkid ) : parent ); + } /* ubi_btLocate */ + +ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_btLocate(). + * ------------------------------------------------------------------------ ** + */ + { + return( qFind( RootPtr->cmp, FindMe, RootPtr->root ) ); + } /* ubi_btFind */ + +ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Next node in the + * tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "next" node in the tree, or NULL if P pointed + * to the "last" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + { + return( Neighbor( P, ubi_trRIGHT ) ); + } /* ubi_btNext */ + +ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Previous node in + * the tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "previous" node in the tree, or NULL if P + * pointed to the "first" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + { + return( Neighbor( P, ubi_trLEFT ) ); + } /* ubi_btPrev */ + +ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) First node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "first" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + { + return( SubSlide( P, ubi_trLEFT ) ); + } /* ubi_btFirst */ + +ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Last node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "last" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + { + return( SubSlide( P, ubi_trRIGHT ) ); + } /* ubi_btLast */ + +ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the first (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the first node in the set of nodes with keys + * matching . + * Notes: Node *p MUST be in the set of nodes with keys matching + * . If not, this function will return NULL. + * + * 4.7: Bug found & fixed by Massimo Campostrini, + * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa. + * + * ------------------------------------------------------------------------ ** + */ + { + /* If our starting point is invalid, return NULL. */ + if( (NULL == p) + || (ubi_trEQUAL != ubi_trAbNormal( (*(RootPtr->cmp))( MatchMe, p ) )) ) + return( NULL ); + return( Border( RootPtr, MatchMe, p, ubi_trLEFT ) ); + } /* ubi_btFirstOf */ + +ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the last (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the last node in the set of nodes with keys + * matching . + * Notes: Node *p MUST be in the set of nodes with keys matching + * . If not, this function will return NULL. + * + * 4.7: Bug found & fixed by Massimo Campostrini, + * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa. + * + * ------------------------------------------------------------------------ ** + */ + { + /* If our starting point is invalid, return NULL. */ + if( (NULL != p) + || (ubi_trEQUAL != ubi_trAbNormal( (*(RootPtr->cmp))( MatchMe, p ) )) ) + return( NULL ); + return( Border( RootPtr, MatchMe, p, ubi_trRIGHT ) ); + } /* ubi_btLastOf */ + +unsigned long ubi_btTraverse( ubi_btRootPtr RootPtr, + ubi_btActionRtn EachNode, + void *UserData ) + /* ------------------------------------------------------------------------ ** + * Traverse a tree in sorted order (non-recursively). At each node, call + * (*EachNode)(), passing a pointer to the current node, and UserData as the + * second parameter. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the tree to be traversed. + * EachNode - a pointer to a function to be called at each node + * as the node is visited. + * UserData - a generic pointer that may point to anything that + * you choose. + * + * Output: A count of the number of nodes visited. This will be zero + * if the tree is empty. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p = ubi_btFirst( RootPtr->root ); + unsigned long count = 0; + + while( NULL != p ) + { + (*EachNode)( p, UserData ); + count++; + p = ubi_btNext( p ); + } + return( count ); + } /* ubi_btTraverse */ + +unsigned long ubi_btKillTree( ubi_btRootPtr RootPtr, + ubi_btKillNodeRtn FreeNode ) + /* ------------------------------------------------------------------------ ** + * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot + * structure. Return a count of the number of nodes deleted. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the root of the tree to delete. + * FreeNode - a function that will be called for each node in the + * tree to deallocate the memory used by the node. + * + * Output: The number of nodes removed from the tree. + * A value of 0 will be returned if: + * - The tree actually contains 0 entries. + * - the value of is NULL, in which case the tree is + * assumed to be empty + * - the value of is NULL, in which case entries + * cannot be removed, so 0 is returned. *Make sure that you + * provide a valid value for *. + * In all other cases, you should get a positive value equal to + * the value of RootPtr->count upon entry. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p, q; + unsigned long count = 0; + + if( (NULL == RootPtr) || (NULL == FreeNode) ) + return( 0 ); + + p = ubi_btFirst( RootPtr->root ); + while( NULL != p ) + { + q = p; + while( q->Link[ubi_trRIGHT] ) + q = SubSlide( q->Link[ubi_trRIGHT], ubi_trLEFT ); + p = q->Link[ubi_trPARENT]; + if( NULL != p ) + p->Link[ ((p->Link[ubi_trLEFT] == q)?ubi_trLEFT:ubi_trRIGHT) ] = NULL; +// (*FreeNode)((void *)q); + (*FreeNode)(q); + count++; + } + + /* overkill... */ + (void)ubi_btInitTree( RootPtr, + RootPtr->cmp, + RootPtr->flags ); + return( count ); + } /* ubi_btKillTree */ + +ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ) + /* ------------------------------------------------------------------------ ** + * Returns a pointer to a leaf node. + * + * Input: leader - Pointer to a node at which to start the descent. + * + * Output: A pointer to a leaf node selected in a somewhat arbitrary + * manner. + * + * Notes: I wrote this function because I was using splay trees as a + * database cache. The cache had a maximum size on it, and I + * needed a way of choosing a node to sacrifice if the cache + * became full. In a splay tree, less recently accessed nodes + * tend toward the bottom of the tree, meaning that leaf nodes + * are good candidates for removal. (I really can't think of + * any other reason to use this function.) + * + In a simple binary tree or an AVL tree, the most recently + * added nodes tend to be nearer the bottom, making this a *bad* + * way to choose which node to remove from the cache. + * + Randomizing the traversal order is probably a good idea. You + * can improve the randomization of leaf node selection by passing + * in pointers to nodes other than the root node each time. A + * pointer to any node in the tree will do. Of course, if you + * pass a pointer to a leaf node you'll get the same thing back. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr follower = NULL; + int whichway = ubi_trLEFT; + + while( NULL != leader ) + { + follower = leader; + leader = follower->Link[ whichway ]; + if( NULL == leader ) + { + whichway = ubi_trRevWay( whichway ); + leader = follower->Link[ whichway ]; + } + } + + return( follower ); + } /* ubi_btLeafNode */ + +int ubi_btModuleID( int size, char *list[] ) + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array . + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of that were used. If this value + * is less than , the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + { + if( size > 0 ) + { + list[0] = ModuleID; + if( size > 1 ) + list[1] = NULL; + return( 1 ); + } + return( 0 ); + } /* ubi_btModuleID */ + + +/* ========================================================================== */ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_BinTree.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_BinTree.h new file mode 100644 index 0000000000..2a14a70b88 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_BinTree.h @@ -0,0 +1,864 @@ +#ifndef UBI_BINTREE_H +#define UBI_BINTREE_H +/* ========================================================================== ** + * ubi_BinTree.h + * + * Copyright (C) 1991-1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements a simple binary tree. + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_BinTree.h,v $ + * Revision 4.10 2000/06/06 20:38:40 crh + * In the ReplaceNode() function, the old node header was being copied + * to the new node header using a byte-by-byte copy. This was causing + * the 'insure' software testing program to report a memory leak. The + * fix was to do a simple assignement: *newnode = *oldnode; + * This quieted the (errant) memory leak reports and is probably a bit + * faster than the bytewise copy. + * + * Revision 4.9 2000/01/08 23:24:30 crh + * Clarified a variety of if( pointer ) lines, replacing them with + * if( NULL != pointer ). This is more correct, and I have heard + * of at least one (obscure?) system out there that uses a non-zero + * value for NULL. + * Also, speed improvement in Neighbor(). It was comparing pointers + * when it could have compared two gender values. The pointer + * comparison was somewhat indirect (does pointer equal the pointer + * of the parent of the node pointed to by pointer). Urq. + * + * Revision 4.8 1999/09/22 03:40:30 crh + * Modified ubi_btTraverse() and ubi_btKillTree(). They now return an + * unsigned long indicating the number of nodes processed. The change + * is subtle. An empty tree formerly returned False, and now returns + * zero. + * + * Revision 4.7 1998/10/21 06:15:07 crh + * Fixed bugs in FirstOf() and LastOf() reported by Massimo Campostrini. + * See function comments. + * + * Revision 4.6 1998/07/25 17:02:10 crh + * Added the ubi_trNewTree() macro. + * + * Revision 4.5 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 4.4 1998/06/03 17:42:46 crh + * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is + * included by all of the binary tree files. + * + * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in + * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping + * of tree types by simply changing a header. Unfortunately, the + * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will + * conflict if used together. You must either choose a single tree + * type, or use the underlying function calls directly. Compare + * the two header files for more information. + * + * Revision 4.3 1998/06/02 01:28:43 crh + * Changed ubi_null.h to sys_include.h to make it more generic. + * + * Revision 4.2 1998/05/20 04:32:36 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * Also, the balance and gender fields of the node were declared as + * signed char. As I understand it, at least one SunOS or Solaris + * compiler doesn't like "signed char". The declarations were + * wrong anyway, so I changed them to simple "char". + * + * Revision 4.1 1998/03/31 06:13:47 crh + * Thomas Aglassinger sent E'mail pointing out errors in the + * dereferencing of function pointers, and a missing typecast. + * Thanks, Thomas! + * + * Revision 4.0 1998/03/10 03:16:04 crh + * Added the AVL field 'balance' to the ubi_btNode structure. This means + * that all BinTree modules now use the same basic node structure, which + * greatly simplifies the AVL module. + * Decided that this was a big enough change to justify a new major revision + * number. 3.0 was an error, so we're at 4.0. + * + * Revision 2.6 1998/01/24 06:27:30 crh + * Added ubi_trCount() macro. + * + * Revision 2.5 1997/12/23 03:59:21 crh + * In this version, all constants & macros defined in the header file have + * the ubi_tr prefix. Also cleaned up anything that gcc complained about + * when run with '-pedantic -fsyntax-only -Wall'. + * + * Revision 2.4 1997/07/26 04:11:14 crh + * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE + * and ubi_trFALSE. + * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. + * + There used to be something called "ubi_TypeDefs.h". I got rid of it. + * + Added function ubi_btLeafNode(). + * + * Revision 2.3 1997/06/03 05:15:27 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. + * Also changed the interface to function InitTree(). See the comments + * for this function for more information. + * + * Revision 2.2 1995/10/03 22:00:40 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:43:46 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:00:33 CRH + * Revision 2.0 of this program includes the following changes: + * + * 1) A fix to a major typo in the RepaceNode() function. + * 2) The addition of the static function Border(). + * 3) The addition of the public functions FirstOf() and LastOf(), which + * use Border(). These functions are used with trees that allow + * duplicate keys. + * 4) A complete rewrite of the Locate() function. Locate() now accepts + * a "comparison" operator. + * 5) Overall enhancements to both code and comments. + * + * I decided to give this a new major rev number because the interface has + * changed. In particular, there are two new functions, and changes to the + * Locate() function. + * + * Revision 1.0 93/10/15 22:55:04 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_SplayTree, the locate function was + * called "ubi_sptLocate", but the next and previous functions remained + * "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================== ** + */ + +//#include "sys_include.h" /* Global include file, used to adapt the ubiqx +// * modules to the host environment and the project +// * with which the modules will be used. See +// * sys_include.h for more info. +// */ + +/* -------------------------------------------------------------------------- ** + * Macros and constants. + * + * General purpose: + * ubi_trTRUE - Boolean TRUE. + * ubi_trFALSE - Boolean FALSE. + * + * Flags used in the tree header: + * ubi_trOVERWRITE - This flag indicates that an existing node may be + * overwritten by a new node with a matching key. + * ubi_trDUPKEY - This flag indicates that the tree allows duplicate + * keys. If the tree does allow duplicates, the + * overwrite flag is ignored. + * + * Node link array index constants: (Each node has an array of three + * pointers. One to the left, one to the right, and one back to the + * parent.) + * ubi_trLEFT - Left child pointer. + * ubi_trPARENT - Parent pointer. + * ubi_trRIGHT - Right child pointer. + * ubi_trEQUAL - Synonym for PARENT. + * + * ubi_trCompOps: These values are used in the ubi_trLocate() function. + * ubi_trLT - request the first instance of the greatest key less than + * the search key. + * ubi_trLE - request the first instance of the greatest key that is less + * than or equal to the search key. + * ubi_trEQ - request the first instance of key that is equal to the + * search key. + * ubi_trGE - request the first instance of a key that is greater than + * or equal to the search key. + * ubi_trGT - request the first instance of the first key that is greater + * than the search key. + * -------------------------------------------------------------------------- ** + */ + +#define ubi_trTRUE 0xFF +#define ubi_trFALSE 0x00 + +#define ubi_trOVERWRITE 0x01 /* Turn on allow overwrite */ +#define ubi_trDUPKEY 0x02 /* Turn on allow duplicate keys */ + +/* Pointer array index constants... */ +#define ubi_trLEFT 0x00 +#define ubi_trPARENT 0x01 +#define ubi_trRIGHT 0x02 +#define ubi_trEQUAL ubi_trPARENT + +typedef enum { + ubi_trLT = 1, + ubi_trLE, + ubi_trEQ, + ubi_trGE, + ubi_trGT + } ubi_trCompOps; + +/* -------------------------------------------------------------------------- ** + * These three macros allow simple manipulation of pointer index values (LEFT, + * RIGHT, and PARENT). + * + * Normalize() - converts {LEFT, PARENT, RIGHT} into {-1, 0 ,1}. C + * uses {negative, zero, positive} values to indicate + * {less than, equal to, greater than}. + * AbNormal() - converts {negative, zero, positive} to {LEFT, PARENT, + * RIGHT} (opposite of Normalize()). Note: C comparison + * functions, such as strcmp(), return {negative, zero, + * positive} values, which are not necessarily {-1, 0, + * 1}. This macro uses the the ubi_btSgn() function to + * compensate. + * RevWay() - converts LEFT to RIGHT and RIGHT to LEFT. PARENT (EQUAL) + * is left as is. + * -------------------------------------------------------------------------- ** + */ +#define ubi_trNormalize(W) ((char)( (W) - ubi_trEQUAL )) +#define ubi_trAbNormal(W) ((char)( ((char)ubi_btSgn( (long)(W) )) \ + + ubi_trEQUAL )) +#define ubi_trRevWay(W) ((char)( ubi_trEQUAL - ((W) - ubi_trEQUAL) )) + +/* -------------------------------------------------------------------------- ** + * These macros allow us to quickly read the values of the OVERWRITE and + * DUPlicate KEY bits of the tree root flags field. + * -------------------------------------------------------------------------- ** + */ +#define ubi_trDups_OK(A) \ + ((ubi_trDUPKEY & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) +#define ubi_trOvwt_OK(A) \ + ((ubi_trOVERWRITE & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) + +/* -------------------------------------------------------------------------- ** + * Additional Macros... + * + * ubi_trCount() - Given a pointer to a tree root, this macro returns the + * number of nodes currently in the tree. + * + * ubi_trNewTree() - This macro makes it easy to declare and initialize a + * tree header in one step. The line + * + * static ubi_trNewTree( MyTree, cmpfn, ubi_trDUPKEY ); + * + * is equivalent to + * + * static ubi_trRoot MyTree[1] + * = {{ NULL, cmpfn, 0, ubi_trDUPKEY }}; + * + * -------------------------------------------------------------------------- ** + */ + +#define ubi_trCount( R ) (((ubi_trRootPtr)(R))->count) + +#define ubi_trNewTree( N, C, F ) ubi_trRoot (N)[1] = {{ NULL, (C), 0, (F) }} + +/* -------------------------------------------------------------------------- ** + * Typedefs... + * + * ubi_trBool - Your typcial true or false... + * + * Item Pointer: The ubi_btItemPtr is a generic pointer. It is used to + * indicate a key that is being searched for within the tree. + * Searching occurs whenever the ubi_trFind(), ubi_trLocate(), + * or ubi_trInsert() functions are called. + * -------------------------------------------------------------------------- ** + */ + +typedef unsigned char ubi_trBool; + +typedef void *ubi_btItemPtr; /* A pointer to key data within a node. */ + +/* ------------------------------------------------------------------------- ** + * Binary Tree Node Structure: This structure defines the basic elements of + * the tree nodes. In general you *SHOULD NOT PLAY WITH THESE FIELDS*! + * But, of course, I have to put the structure into this header so that + * you can use it as a building block. + * + * The fields are as follows: + * Link - an array of pointers. These pointers are manipulated by + * the BT routines. The pointers indicate the left and right + * child nodes and the parent node. By keeping track of the + * parent pointer, we avoid the need for recursive routines or + * hand-tooled stacks to keep track of our path back to the + * root. The use of these pointers is subject to change without + * notice. + * gender - a one-byte field indicating whether the node is the RIGHT or + * LEFT child of its parent. If the node is the root of the + * tree, gender will be PARENT. + * balance - only used by the AVL tree module. This field indicates + * the height balance at a given node. See ubi_AVLtree for + * details. + * + * ------------------------------------------------------------------------- ** + */ +typedef struct ubi_btNodeStruct { + struct ubi_btNodeStruct *Link[ 3 ]; + char gender; + char balance; + } ubi_btNode; + +typedef ubi_btNode *ubi_btNodePtr; /* Pointer to an ubi_btNode structure. */ + +/* ------------------------------------------------------------------------- ** + * The next three typedefs define standard function types used by the binary + * tree management routines. In particular: + * + * ubi_btCompFunc is a pointer to a comparison function. Comparison + * functions are passed an ubi_btItemPtr and an + * ubi_btNodePtr. They return a value that is (<0), 0, + * or (>0) to indicate that the Item is (respectively) + * "less than", "equal to", or "greater than" the Item + * contained within the node. (See ubi_btInitTree()). + * ubi_btActionRtn is a pointer to a function that may be called for each + * node visited when performing a tree traversal (see + * ubi_btTraverse()). The function will be passed two + * parameters: the first is a pointer to a node in the + * tree, the second is a generic pointer that may point to + * anything that you like. + * ubi_btKillNodeRtn is a pointer to a function that will deallocate the + * memory used by a node (see ubi_btKillTree()). Since + * memory management is left up to you, deallocation may + * mean anything that you want it to mean. Just remember + * that the tree *will* be destroyed and that none of the + * node pointers will be valid any more. + * ------------------------------------------------------------------------- ** + */ + +typedef int (*ubi_btCompFunc)( ubi_btItemPtr, ubi_btNodePtr ); + +typedef void (*ubi_btActionRtn)( ubi_btNodePtr, void * ); + +typedef void (*ubi_btKillNodeRtn)( ubi_btNodePtr ); + +/* -------------------------------------------------------------------------- ** + * Tree Root Structure: This structure gives us a convenient handle for + * accessing whole binary trees. The fields are: + * root - A pointer to the root node of the tree. + * count - A count of the number of nodes stored in the tree. + * cmp - A pointer to the comparison routine to be used when building or + * searching the tree. + * flags - A set of bit flags. Two flags are currently defined: + * + * ubi_trOVERWRITE - If set, this flag indicates that a new node should + * (bit 0x01) overwrite an old node if the two have identical + * keys (ie., the keys are equal). + * ubi_trDUPKEY - If set, this flag indicates that the tree is + * (bit 0x02) allowed to contain nodes with duplicate keys. + * + * NOTE: ubi_trInsert() tests ubi_trDUPKEY before ubi_trOVERWRITE. + * + * All of these values are set when you initialize the root structure by + * calling ubi_trInitTree(). + * -------------------------------------------------------------------------- ** + */ + +typedef struct { + ubi_btNodePtr root; /* A pointer to the root node of the tree */ + ubi_btCompFunc cmp; /* A pointer to the tree's comparison function */ + unsigned long count; /* A count of the number of nodes in the tree */ + char flags; /* Overwrite Y|N, Duplicate keys Y|N... */ + } ubi_btRoot; + +typedef ubi_btRoot *ubi_btRootPtr; /* Pointer to an ubi_btRoot structure. */ + + +/* -------------------------------------------------------------------------- ** + * Function Prototypes. + */ + +long ubi_btSgn( long x ); + /* ------------------------------------------------------------------------ ** + * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. + * + * Input: x - a signed long integer value. + * + * Output: the "sign" of x, represented as follows: + * -1 == negative + * 0 == zero (no sign) + * 1 == positive + * + * Note: This utility is provided in order to facilitate the conversion + * of C comparison function return values into BinTree direction + * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the + * AbNormal() conversion macro! + * + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: a pointer to a ubi_btNode structure to be initialized. + * Output: a pointer to the initialized ubi_btNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + +ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, + ubi_btCompFunc CompFunc, + char Flags ); + /* ------------------------------------------------------------------------ ** + * Initialize the fields of a Tree Root header structure. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure to be + * initialized. + * CompFunc - a pointer to a comparison function that will be used + * whenever nodes in the tree must be compared against + * outside values. + * Flags - One bytes worth of flags. Flags include + * ubi_trOVERWRITE and ubi_trDUPKEY. See the header + * file for more info. + * + * Output: a pointer to the initialized ubi_btRoot structure (ie. the + * same value as RootPtr). + * + * Note: The interface to this function has changed from that of + * previous versions. The parameter replaces two + * boolean parameters that had the same basic effect. + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ); + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, + ubi_btNodePtr DeadNode ); + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ); + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ); + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_btLocate(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Next node in the + * tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "next" node in the tree, or NULL if P pointed + * to the "last" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Previous node in + * the tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "previous" node in the tree, or NULL if P + * pointed to the "first" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) First node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "first" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Last node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "last" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ); + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the first (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the first node in the set of nodes with keys + * matching . + * Notes: Node *p MUST be in the set of nodes with keys matching + * . If not, this function will return NULL. + * + * 4.7: Bug found & fixed by Massimo Campostrini, + * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa. + * + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ); + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the last (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the last node in the set of nodes with keys + * matching . + * Notes: Node *p MUST be in the set of nodes with keys matching + * . If not, this function will return NULL. + * + * 4.7: Bug found & fixed by Massimo Campostrini, + * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa. + * + * ------------------------------------------------------------------------ ** + */ + +unsigned long ubi_btTraverse( ubi_btRootPtr RootPtr, + ubi_btActionRtn EachNode, + void *UserData ); + /* ------------------------------------------------------------------------ ** + * Traverse a tree in sorted order (non-recursively). At each node, call + * (*EachNode)(), passing a pointer to the current node, and UserData as the + * second parameter. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the tree to be traversed. + * EachNode - a pointer to a function to be called at each node + * as the node is visited. + * UserData - a generic pointer that may point to anything that + * you choose. + * + * Output: A count of the number of nodes visited. This will be zero + * if the tree is empty. + * + * ------------------------------------------------------------------------ ** + */ + + +unsigned long ubi_btKillTree( ubi_btRootPtr RootPtr, + ubi_btKillNodeRtn FreeNode ); + /* ------------------------------------------------------------------------ ** + * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot + * structure. Return a count of the number of nodes deleted. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the root of the tree to delete. + * FreeNode - a function that will be called for each node in the + * tree to deallocate the memory used by the node. + * + * Output: The number of nodes removed from the tree. + * A value of 0 will be returned if: + * - The tree actually contains 0 entries. + * - the value of is NULL, in which case the tree is + * assumed to be empty + * - the value of is NULL, in which case entries + * cannot be removed, so 0 is returned. *Make sure that you + * provide a valid value for *. + * In all other cases, you should get a positive value equal to + * the value of RootPtr->count upon entry. + * + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ); + /* ------------------------------------------------------------------------ ** + * Returns a pointer to a leaf node. + * + * Input: leader - Pointer to a node at which to start the descent. + * + * Output: A pointer to a leaf node selected in a somewhat arbitrary + * manner. + * + * Notes: I wrote this function because I was using splay trees as a + * database cache. The cache had a maximum size on it, and I + * needed a way of choosing a node to sacrifice if the cache + * became full. In a splay tree, less recently accessed nodes + * tend toward the bottom of the tree, meaning that leaf nodes + * are good candidates for removal. (I really can't think of + * any other reason to use this function.) + * + In a simple binary tree or an AVL tree, the most recently + * added nodes tend to be nearer the bottom, making this a *bad* + * way to choose which node to remove from the cache. + * + Randomizing the traversal order is probably a good idea. You + * can improve the randomization of leaf node selection by passing + * in pointers to nodes other than the root node each time. A + * pointer to any node in the tree will do. Of course, if you + * pass a pointer to a leaf node you'll get the same thing back. + * + * ------------------------------------------------------------------------ ** + */ + + +int ubi_btModuleID( int size, char *list[] ); + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array . + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of that were used. If this value + * is less than , the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- ** + * Masquarade... + * + * This set of defines allows you to write programs that will use any of the + * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). + * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by + * including the appropriate module header. + */ + +#define ubi_trItemPtr ubi_btItemPtr + +#define ubi_trNode ubi_btNode +#define ubi_trNodePtr ubi_btNodePtr + +#define ubi_trRoot ubi_btRoot +#define ubi_trRootPtr ubi_btRootPtr + +#define ubi_trCompFunc ubi_btCompFunc +#define ubi_trActionRtn ubi_btActionRtn +#define ubi_trKillNodeRtn ubi_btKillNodeRtn + +#define ubi_trSgn( x ) ubi_btSgn( x ) + +#define ubi_trInitNode( Np ) ubi_btInitNode( (ubi_btNodePtr)(Np) ) + +#define ubi_trInitTree( Rp, Cf, Fl ) \ + ubi_btInitTree( (ubi_btRootPtr)(Rp), (ubi_btCompFunc)(Cf), (Fl) ) + +#define ubi_trInsert( Rp, Nn, Ip, On ) \ + ubi_btInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ + (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) + +#define ubi_trRemove( Rp, Dn ) \ + ubi_btRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) + +#define ubi_trLocate( Rp, Ip, Op ) \ + ubi_btLocate( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_trCompOps)(Op) ) + +#define ubi_trFind( Rp, Ip ) \ + ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) + +#define ubi_trNext( P ) ubi_btNext( (ubi_btNodePtr)(P) ) + +#define ubi_trPrev( P ) ubi_btPrev( (ubi_btNodePtr)(P) ) + +#define ubi_trFirst( P ) ubi_btFirst( (ubi_btNodePtr)(P) ) + +#define ubi_trLast( P ) ubi_btLast( (ubi_btNodePtr)(P) ) + +#define ubi_trFirstOf( Rp, Ip, P ) \ + ubi_btFirstOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#define ubi_trLastOf( Rp, Ip, P ) \ + ubi_btLastOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#define ubi_trTraverse( Rp, En, Ud ) \ + ubi_btTraverse((ubi_btRootPtr)(Rp), (ubi_btActionRtn)(En), (void *)(Ud)) + +#define ubi_trKillTree( Rp, Fn ) \ + ubi_btKillTree( (ubi_btRootPtr)(Rp), (ubi_btKillNodeRtn)(Fn) ) + +#define ubi_trLeafNode( Nd ) \ + ubi_btLeafNode( (ubi_btNodePtr)(Nd) ) + +#define ubi_trModuleID( s, l ) ubi_btModuleID( s, l ) + +/* ========================================================================== */ +#endif /* UBI_BINTREE_H */ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_SplayTree.cpp b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_SplayTree.cpp new file mode 100644 index 0000000000..d3bbf13a18 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_SplayTree.cpp @@ -0,0 +1,513 @@ +/* ========================================================================== ** + * ubi_SplayTree.c + * + * Copyright (C) 1993-1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements "splay" trees. Splay trees are binary trees + * that are rearranged (splayed) whenever a node is accessed. The + * splaying process *tends* to make the tree bushier (improves balance), + * and the nodes that are accessed most frequently *tend* to be closer to + * the top. + * + * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and + * Robert Tarjan. Journal of the Association for Computing + * Machinery Vol 32, No. 3, July 1985 pp. 652-686 + * + * See also: http://www.cs.cmu.edu/~sleator/ + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_SplayTree.c,v $ + * Revision 4.5 2000/01/08 23:26:49 crh + * Added ubi_trSplay() macro, which does a type cast for us. + * + * Revision 4.4 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 4.3 1998/06/03 17:45:05 crh + * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is + * included by all of the binary tree files. + * + * Also fixed some warnings produced by lint on Irix 6.2, which doesn't seem + * to like syntax like this: + * + * if( (a = b) ) + * + * The fix was to change lines like the above to: + * + * if( 0 != (a=b) ) + * + * Which means the same thing. + * + * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in + * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping + * of tree types by simply changing a header. Unfortunately, the + * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will + * conflict if used together. You must either choose a single tree + * type, or use the underlying function calls directly. Compare + * the two header files for more information. + * + * Revision 4.2 1998/06/02 01:29:14 crh + * Changed ubi_null.h to sys_include.h to make it more generic. + * + * Revision 4.1 1998/05/20 04:37:54 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 4.0 1998/03/10 03:41:33 crh + * Minor comment changes. The revision number is now 4.0 to match the + * BinTree and AVLtree modules. + * + * Revision 2.7 1998/01/24 06:37:08 crh + * Added a URL for more information. + * + * Revision 2.6 1997/12/23 04:01:12 crh + * In this version, all constants & macros defined in the header file have + * the ubi_tr prefix. Also cleaned up anything that gcc complained about + * when run with '-pedantic -fsyntax-only -Wall'. + * + * Revision 2.5 1997/07/26 04:15:42 crh + * + Cleaned up a few minor syntax annoyances that gcc discovered for me. + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + * Revision 2.4 1997/06/03 04:42:21 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.3 1995/10/03 22:19:07 CRH + * Ubisized! + * Also, added the function ubi_sptSplay(). + * + * Revision 2.1 95/03/09 23:54:42 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:34:46 CRH + * This module was updated to match the interface changes made to the + * ubi_BinTree module. In particular, the interface to the Locate() function + * has changed. See ubi_BinTree for more information on changes and new + * functions. + * + * The revision number was also upped to match ubi_BinTree. + * + * Revision 1.1 93/10/18 20:35:16 CRH + * I removed the hard-coded logical device names from the include file + * specifications. CRH + * + * Revision 1.0 93/10/15 23:00:15 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_SplayTree, the locate function was + * called "ubi_sptLocate", but the next and previous functions remained + * "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * Revision 0.1 93/04/25 22:03:32 CRH + * Simply changed the #include reference the .c file to + * use instead. The latter is portable, the former is not. + * + * Revision 0.0 93/04/21 23:05:52 CRH + * Initial version, written by Christopher R. Hertel. + * This module implements Splay Trees using the ubi_BinTree module as a basis. + * + * ========================================================================== ** + */ + +#include "stdafx.h" + +#include "ubi_SplayTree.h" /* Header for THIS module. */ + +/* ========================================================================== ** + * Static data. + */ + +static char ModuleID[] = "ubi_SplayTree\n\ +\t$Revision: 4.5 $\n\ +\t$Date: 2000/01/08 23:26:49 $\n\ +\t$Author: crh $\n"; + + +/* ========================================================================== ** + * Private functions... + */ + +static void Rotate( ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * This function performs a single rotation, moving node *p up one level + * in the tree. + * + * Input: p - a pointer to an ubi_btNode in a tree. + * + * Output: None. + * + * Notes: This implements a single rotation in either direction (left + * or right). This is the basic building block of all splay + * tree rotations. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr parentp; + ubi_btNodePtr tmp; + char way; + char revway; + + parentp = p->Link[ubi_trPARENT]; /* Find parent. */ + + if( parentp ) /* If no parent, then we're already the root. */ + { + way = p->gender; + revway = ubi_trRevWay(way); + tmp = p->Link[(int)revway]; + + parentp->Link[(int)way] = tmp; + if( tmp ) + { + tmp->Link[ubi_trPARENT] = parentp; + tmp->gender = way; + } + + tmp = parentp->Link[ubi_trPARENT]; + p->Link[ubi_trPARENT] = tmp; + p->gender = parentp->gender; + if( tmp ) + tmp->Link[(int)(p->gender)] = p; + + parentp->Link[ubi_trPARENT] = p; + parentp->gender = revway; + p->Link[(int)revway] = parentp; + } + } /* Rotate */ + +static ubi_btNodePtr Splay( ubi_btNodePtr SplayWithMe ) + /* ------------------------------------------------------------------------ ** + * Move the node indicated by SplayWithMe to the root of the tree by + * splaying the tree. + * + * Input: SplayWithMe - A pointer to an ubi_btNode within a tree. + * + * Output: A pointer to the root of the splay tree (i.e., the same as + * SplayWithMe). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr parent; + + while( NULL != (parent = SplayWithMe->Link[ubi_trPARENT]) ) + { + if( parent->gender == SplayWithMe->gender ) /* Zig-Zig */ + Rotate( parent ); + else + { + if( ubi_trEQUAL != parent->gender ) /* Zig-Zag */ + Rotate( SplayWithMe ); + } + Rotate( SplayWithMe ); /* Zig */ + } /* while */ + return( SplayWithMe ); + } /* Splay */ + +/* ========================================================================== ** + * Exported utilities. + */ + +ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ) + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * splay tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr OtherP; + + if( !(OldNode) ) + OldNode = &OtherP; + + if( ubi_btInsert( RootPtr, NewNode, ItemPtr, OldNode ) ) + { + RootPtr->root = Splay( NewNode ); + return( ubi_trTRUE ); + } + + /* Splay the unreplacable, duplicate keyed, unique, old node. */ + RootPtr->root = Splay( (*OldNode) ); + return( ubi_trFALSE ); + } /* ubi_sptInsert */ + +ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ) + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + (void)Splay( DeadNode ); /* Move dead node to root. */ + if( NULL != (p = DeadNode->Link[ubi_trLEFT]) ) + { /* If left subtree exists... */ + ubi_btNodePtr q = DeadNode->Link[ubi_trRIGHT]; + + p->Link[ubi_trPARENT] = NULL; /* Left subtree node becomes root.*/ + p->gender = ubi_trPARENT; + p = ubi_btLast( p ); /* Find rightmost left node... */ + p->Link[ubi_trRIGHT] = q; /* ...attach right tree. */ + if( q ) + q->Link[ubi_trPARENT] = p; + RootPtr->root = Splay( p ); /* Resplay at p. */ + } + else + { + if( NULL != (p = DeadNode->Link[ubi_trRIGHT]) ) + { /* No left, but right subtree exists... */ + p->Link[ubi_trPARENT] = NULL; /* Right subtree root becomes... */ + p->gender = ubi_trPARENT; /* ...overall tree root. */ + RootPtr->root = p; + } + else + RootPtr->root = NULL; /* No subtrees => empty tree. */ + } + + (RootPtr->count)--; /* Decrement node count. */ + return( DeadNode ); /* Return pointer to pruned node. */ + } /* ubi_sptRemove */ + +ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ) + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + p = ubi_btLocate( RootPtr, FindMe, CompOp ); + if( p ) + RootPtr->root = Splay( p ); + return( p ); + } /* ubi_sptLocate */ + +ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_sptLocate(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + p = ubi_btFind( RootPtr, FindMe ); + if( p ) + RootPtr->root = Splay( p ); + return( p ); + } /* ubi_sptFind */ + +void ubi_sptSplay( ubi_btRootPtr RootPtr, + ubi_btNodePtr SplayMe ) + /* ------------------------------------------------------------------------ ** + * This function allows you to splay the tree at a given node, thus moving + * the node to the top of the tree. + * + * Input: + * RootPtr - a pointer to the header of the tree to be splayed. + * SplayMe - a pointer to a node within the tree. This will become + * the new root node. + * Output: None. + * + * Notes: This is an uncharacteristic function for this group of modules + * in that it provides access to the internal balancing routines, + * which would normally be hidden. + * Splaying the tree will not damage it (assuming that I've done + * *my* job), but there is overhead involved. I don't recommend + * that you use this function unless you understand the underlying + * Splay Tree principles involved. + * ------------------------------------------------------------------------ ** + */ + { + RootPtr->root = Splay( SplayMe ); + } /* ubi_sptSplay */ + +int ubi_sptModuleID( int size, char *list[] ) + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array . + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of that were used. If this value + * is less than , the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + { + if( size > 0 ) + { + list[0] = ModuleID; + if( size > 1 ) + return( 1 + ubi_btModuleID( --size, &(list[1]) ) ); + return( 1 ); + } + return( 0 ); + } /* ubi_sptModuleID */ + +/* ================================ The End ================================= */ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_SplayTree.h b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_SplayTree.h new file mode 100644 index 0000000000..246e84ba2c --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server-Windows/ubi_SplayTree.h @@ -0,0 +1,377 @@ +#ifndef UBI_SPLAYTREE_H +#define UBI_SPLAYTREE_H +/* ========================================================================== ** + * ubi_SplayTree.h + * + * Copyright (C) 1993-1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements "splay" trees. Splay trees are binary trees + * that are rearranged (splayed) whenever a node is accessed. The + * splaying process *tends* to make the tree bushier (improves balance), + * and the nodes that are accessed most frequently *tend* to be closer to + * the top. + * + * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and + * Robert Tarjan. Journal of the Association for Computing + * Machinery Vol 32, No. 3, July 1985 pp. 652-686 + * + * See also: http://www.cs.cmu.edu/~sleator/ + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_SplayTree.h,v $ + * Revision 4.5 2000/01/08 23:26:49 crh + * Added ubi_trSplay() macro, which does a type cast for us. + * + * Revision 4.4 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 4.3 1998/06/03 17:45:05 crh + * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is + * included by all of the binary tree files. + * + * Also fixed some warnings produced by lint on Irix 6.2, which doesn't seem + * to like syntax like this: + * + * if( (a = b) ) + * + * The fix was to change lines like the above to: + * + * if( 0 != (a=b) ) + * + * Which means the same thing. + * + * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in + * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping + * of tree types by simply changing a header. Unfortunately, the + * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will + * conflict if used together. You must either choose a single tree + * type, or use the underlying function calls directly. Compare + * the two header files for more information. + * + * Revision 4.2 1998/06/02 01:29:14 crh + * Changed ubi_null.h to sys_include.h to make it more generic. + * + * Revision 4.1 1998/05/20 04:37:54 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 4.0 1998/03/10 03:40:57 crh + * Minor comment changes. The revision number is now 4.0 to match the + * BinTree and AVLtree modules. + * + * Revision 2.7 1998/01/24 06:37:57 crh + * Added a URL for more information. + * + * Revision 2.6 1997/12/23 04:02:20 crh + * In this version, all constants & macros defined in the header file have + * the ubi_tr prefix. Also cleaned up anything that gcc complained about + * when run with '-pedantic -fsyntax-only -Wall'. + * + * Revision 2.5 1997/07/26 04:15:46 crh + * + Cleaned up a few minor syntax annoyances that gcc discovered for me. + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + * Revision 2.4 1997/06/03 05:22:56 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.3 1995/10/03 22:19:37 CRH + * Ubisized! + * Also, added the function ubi_sptSplay(). + * + * Revision 2.1 95/03/09 23:55:04 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:34:55 CRH + * This module was updated to match the interface changes made to the + * ubi_BinTree module. In particular, the interface to the Locate() function + * has changed. See ubi_BinTree for more information on changes and new + * functions. + * + * The revision number was also upped to match ubi_BinTree. + * + * + * Revision 1.0 93/10/15 22:59:36 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_SplayTree, the locate function was + * called "ubi_sptLocate", but the next and previous functions remained + * "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * Revision 0.0 93/04/21 23:07:13 CRH + * Initial version, written by Christopher R. Hertel. + * This module implements Splay Trees using the ubi_BinTree module as a basis. + * + * ========================================================================== ** + */ + +#include "ubi_BinTree.h" /* Base binary tree functions, types, etc. */ + +/* ========================================================================== ** + * Function prototypes... + */ + +ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ); + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * splay tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ); + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ); + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ); + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_sptLocate(). + * ------------------------------------------------------------------------ ** + */ + +void ubi_sptSplay( ubi_btRootPtr RootPtr, + ubi_btNodePtr SplayMe ); + /* ------------------------------------------------------------------------ ** + * This function allows you to splay the tree at a given node, thus moving + * the node to the top of the tree. + * + * Input: + * RootPtr - a pointer to the header of the tree to be splayed. + * SplayMe - a pointer to a node within the tree. This will become + * the new root node. + * Output: None. + * + * Notes: This is an uncharacteristic function for this group of modules + * in that it provides access to the internal balancing routines, + * which would normally be hidden. + * Splaying the tree will not damage it (assuming that I've done + * *my* job), but there is overhead involved. I don't recommend + * that you use this function unless you understand the underlying + * Splay Tree principles involved. + * ------------------------------------------------------------------------ ** + */ + +int ubi_sptModuleID( int size, char *list[] ); + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array . + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of that were used. If this value + * is less than , the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- ** + * Masquarade... + * + * This set of defines allows you to write programs that will use any of the + * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). + * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by + * including the appropriate module header. + */ + +#undef ubi_trInsert +#undef ubi_trRemove +#undef ubi_trLocate +#undef ubi_trFind +#undef ubi_trModuleID + +#define ubi_trInsert( Rp, Nn, Ip, On ) \ + ubi_sptInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ + (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) + +#define ubi_trRemove( Rp, Dn ) \ + ubi_sptRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) + +#define ubi_trLocate( Rp, Ip, Op ) \ + ubi_sptLocate( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_trCompOps)(Op) ) + +#define ubi_trFind( Rp, Ip ) \ + ubi_sptFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) + +#define ubi_trSplay( Rp, Sm ) \ + ubi_sptSplay( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Sm) ) + +#define ubi_trModuleID( s, l ) ubi_sptModuleID( s, l ) + +/* ================================ The End ================================= */ +#endif /* UBI_SPLAYTREE_H */ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server/RPCPendingCalls.h b/src/tests/add-ons/kernel/file_systems/beserved/server/RPCPendingCalls.h new file mode 100644 index 0000000000..30693a699e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server/RPCPendingCalls.h @@ -0,0 +1,51 @@ +#ifndef _RPCPENDINGCALLS_H + +#define _RPCPENDINGCALLS_H + +#include +#include +#include + +struct SemaphorePool +{ + sem_id *fPool; + int32 fPoolCount; + int32 fPoolSize; + sem_id fPoolSem; +}; + +void SemaphorePoolInit (struct SemaphorePool *pool); +void SemaphorePoolDestroy (struct SemaphorePool *pool); +sem_id SemaphorePoolGet(struct SemaphorePool *pool); +void SemaphorePoolPut (struct SemaphorePool *pool, sem_id sem); + +struct PendingCall +{ + struct PendingCall *next; + + sem_id sem; + struct sockaddr_in addr; + int32 xid; + uint8 *buffer; +}; + +void PendingCallInit (struct PendingCall *call); +void PendingCallDestroy (struct PendingCall *call); + +struct RPCPendingCalls +{ + struct PendingCall *fFirst; + sem_id fSem; + struct SemaphorePool fPool; +}; + +void RPCPendingCallsInit (struct RPCPendingCalls *calls); +void RPCPendingCallsDestroy (struct RPCPendingCalls *calls); + +struct PendingCall *RPCPendingCallsAddPendingCall (struct RPCPendingCalls *calls, + int32 xid, const struct sockaddr_in *addr); + +struct PendingCall *RPCPendingCallsFindAndRemovePendingCall (struct RPCPendingCalls *calls, + int32 xid, const struct sockaddr_in *addr); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server/Resource.rsrc b/src/tests/add-ons/kernel/file_systems/beserved/server/Resource.rsrc new file mode 100644 index 0000000000..5d27b287df Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server/Resource.rsrc differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server/Server.proj b/src/tests/add-ons/kernel/file_systems/beserved/server/Server.proj new file mode 100644 index 0000000000..09cfc3bf7f Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server/Server.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server/Server_BONE.proj b/src/tests/add-ons/kernel/file_systems/beserved/server/Server_BONE.proj new file mode 100644 index 0000000000..58e906b4a7 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/server/Server_BONE.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server/authentication.c b/src/tests/add-ons/kernel/file_systems/beserved/server/authentication.c new file mode 100644 index 0000000000..40f007062e --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server/authentication.c @@ -0,0 +1,257 @@ +#include "betalk.h" +#include "authentication.h" +#include "sysdepdefs.h" +#include "netdb.h" + +#include "ctype.h" +#include "signal.h" +#include "stdlib.h" + +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket); +int btRPCConnect(unsigned int serverIP, int port); +bool btRPCSend(int session, bt_outPacket *outPacket); +bool btRPCCheckSignature(int session); +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); + + +int btRPCConnect(unsigned int serverIP, int port) +{ + struct sockaddr_in serverAddr; + int session; + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(port); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(serverIP); + + // Create a new socket to receive incoming requests. + session = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (session == INVALID_SOCKET) + return INVALID_SOCKET; + + // Bind that socket to the address constructed above. + if (connect(session, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return INVALID_SOCKET; + + return session; +} + +bool btRPCSend(int session, bt_outPacket *outPacket) +{ + // The XID will be 0. + btRPCPutInt32(outPacket, 0); + btRPCPutChar(outPacket, BT_CMD_TERMINATOR); + + if (btSendMsg(session, outPacket->buffer, outPacket->length, 0) == -1) + return false; + + return true; +} + +bool btRPCCheckSignature(int session) +{ + char signature[20]; + unsigned int sigLen; + + sigLen = strlen(BT_RPC_SIGNATURE); + memset(signature, 0, sigLen); + if (btRecvMsg(session, signature, sigLen, 0) == -1) + return false; + + // Check the signature's validity. + signature[sigLen] = 0; + return (strcmp(signature, BT_RPC_SIGNATURE) == 0); +} + +// btRPCSimpleCall() +// +bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket) +{ + struct timeval timeout; + bt_inPacket *inPacket; + fd_set sockSet; + char *buffer; + int session; + int32 xid, length; + + // Establish a connection with the requested server, on the requested port. + // If we can't connect, abort and return a NULL packet. + inPacket = NULL; + session = btRPCConnect(serverIP, port); + if (session == INVALID_SOCKET) + return NULL; + + // If we connected, send the requested RPC packet. If the packet cannot be + // sent, the connection has dropped and we'll abort the call. + if (!btRPCSend(session, outPacket)) + { + closesocket(session); + return NULL; + } + + // Set a reasonable timeout period. Select() is used in leiu of alarm() because + // select() also aborts on error, alarm() effects all threads in a process. + FD_ZERO(&sockSet); + timeout.tv_sec = 8; + timeout.tv_usec = 0; + + // Block in select() waiting for activity. This will block until data is available + // or until a socket error is pending. + FD_SET(session, &sockSet); + select(session + 1, &sockSet, NULL, NULL, &timeout); + + // If our socket has data pending, then read the incoming RPC response packet. + // This should consist of a valid RPC signature, a tranaction ID (xid), the length + // of the variable data, and the data itself. + if (FD_ISSET(session, &sockSet)) + if (btRPCCheckSignature(session)) + { + if (btRecvMsg(session, &xid, sizeof(int32), 0) == -1 || + btRecvMsg(session, &length, sizeof(int32), 0) == -1) + goto abortCall; + + // Now allocate a buffer of the appropriate length. If one cannot be + // allocated, we won't be able to store incoming information and the call + // must be aborted. + xid = B_LENDIAN_TO_HOST_INT32(xid); + length = B_LENDIAN_TO_HOST_INT32(length); + if (length > 0 && length < BT_RPC_MAX_PACKET_SIZE) + { + buffer = (char *) malloc(length + 1); + if (buffer) + { + // Read the remaining packet contents. The btRecvMsg() function takes + // care of restarting the recv() when signal interrupts occur. It + // will always return -1 on error, even upon orderly shutdown of the peer. + if (btRecvMsg(session, buffer, length, 0) == -1) + { + free(buffer); + goto abortCall; + } + + // Terminate the buffer. + buffer[length] = 0; + + // Allocate a new incoming packet and set its buffer and length. + inPacket = (bt_inPacket *) malloc(sizeof(bt_inPacket)); + if (inPacket) + { + inPacket->buffer = buffer; + inPacket->length = length; + inPacket->offset = 0; + } + else + free(buffer); + } + } + } + + // Execution can naturally lead here or we can jump here from a failed attempt to + // send or receive an RPC packet. The socket is closed and the current incoming + // packet returned, which will be NULL upon failure. +abortCall: + shutdown(session, 2); + close(session); + return inPacket; +} + +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length) +{ + bt_outPacket *packet; + + packet = (bt_outPacket *) malloc(sizeof(bt_outPacket)); + if (!packet) + return NULL; + + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + { + free(packet); + return NULL; + } + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + +// btRPCPutChar(packet, BT_RPC_VERSION_HI); +// btRPCPutChar(packet, BT_RPC_VERSION_LO); + btRPCPutInt32(packet, 7 + (8 * argc) + length); + btRPCPutChar(packet, command); + btRPCPutChar(packet, argc); + + return packet; +} + +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length) +{ + btRPCPutInt32(packet, type); + btRPCPutInt32(packet, length); + btRPCPutBinary(packet, data, length); +} + +bool authenticateUser(char *user, char *password) +{ + extern unsigned int authServerIP; + bt_outPacket *outPacket; + bt_inPacket *inPacket; + bool authenticated = false; + int error; + + outPacket = btRPCPutHeader(BT_CMD_AUTH, 2, strlen(user) + BT_AUTH_TOKEN_LENGTH); + if (outPacket) + { + btRPCPutArg(outPacket, B_STRING_TYPE, user, strlen(user)); + btRPCPutArg(outPacket, B_STRING_TYPE, password, BT_AUTH_TOKEN_LENGTH); + inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket); + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + authenticated = true; + + free(inPacket->buffer); + free(inPacket); + } + + free(outPacket->buffer); + free(outPacket); + } + + return authenticated; +} + +void getUserGroups(char *user, char **groups) +{ + extern unsigned int authServerIP; + bt_outPacket *outPacket; + bt_inPacket *inPacket; + int i, error; + + outPacket = btRPCPutHeader(BT_CMD_WHICHGROUPS, 1, strlen(user)); + if (outPacket) + { + btRPCPutArg(outPacket, B_STRING_TYPE, user, strlen(user)); + inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket); + if (inPacket) + { + i = 0; + error = btRPCGetInt32(inPacket); + while (error == B_OK) + { + groups[i++] = btRPCGetNewString(inPacket); + error = btRPCGetInt32(inPacket); + } + + free(inPacket->buffer); + free(inPacket); + } + + free(outPacket->buffer); + free(outPacket); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server/authentication.h b/src/tests/add-ons/kernel/file_systems/beserved/server/authentication.h new file mode 100644 index 0000000000..8c784ff771 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server/authentication.h @@ -0,0 +1,2 @@ +bool authenticateUser(char *user, char *password); +void getUserGroups(char *user, char **groups); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server/beserved_server.c b/src/tests/add-ons/kernel/file_systems/beserved/server/beserved_server.c new file mode 100644 index 0000000000..5f777f65c2 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server/beserved_server.c @@ -0,0 +1,3691 @@ +// btAdd.cpp : Defines the entry point for the console application. +// + +// To-do: +// +// X Better reconnect logic +// _ Node monitoring +// _ Don't allow following links outside the shared folder +// _ Restart of server erases inode-to-filename map +// _ Ability to reconnect shares at login +// _ Restricting logon times via a schedule +// _ Distributed file sharing +// _ Use a gathered write semaphore per thread, not one global semaphore +// + +// dividing the files: +// 1. main(), start/stop service, request thread launching, misc +// 2. signal handlers +// 3. UDP command thread/handlers +// 4. config file parsing +// 5. RPC code +// 6. actual file handling commands +// 7. net file handling commands + +// Potential Uses: +// 1. Domain server, keeping track of users for logging in +// 2. File server, to share BeOS volume files across a network +// 3. Document management, to store documents with attributes +// 4. Version Control System, to manage multiple versions of documents +// 5. General directory server, for local or network settings and information + +#include "FindDirectory.h" + +#include "betalk.h" +#include "authentication.h" +#include "sysdepdefs.h" +#include "fsproto.h" +#include "netdb.h" + +#include "utime.h" +#include "ctype.h" +#include "time.h" +#include "signal.h" +#include "stdlib.h" +#include "syslog.h" +#include "sys/utsname.h" + +#define BT_MAX_THREADS 100 +#define BT_MAX_RETRIES 3 +#define BT_MAX_FILE_SHARES 128 + +#define BT_MAIN_NAME "BeServed Daemon" +#define BT_THREAD_NAME "BeServed Handler" +#define BT_HOST_THREAD_NAME "BeServed Host Publisher" +#define BT_SIGNATURE "application/x-vnd.Teldar-BeServed" + +#define PATH_ROOT "/boot" +#define PATH_DELIMITER '/' + +#ifndef iswhite +#define iswhite(c) ((c == ' ' || c == '\t')) +#endif + +typedef struct +{ + unsigned int type; + unsigned int length; + char *data; +} bt_arg_t; + +typedef struct btblock +{ + vnode_id vnid; + off_t pos; + int32 len; + int32 count; + char *buffer; + struct btblock *next; + struct btblock *prev; +} bt_block; + +typedef struct userRights +{ + char *user; + int rights; + bool isGroup; + struct userRights *next; +} bt_user_rights; + +typedef struct session +{ + int socket; + unsigned int s_addr; + thread_id handlerID; + + bool killed; + + // What share did the client connect to? And when? + int share; + int rights; + time_t logon; + + // Buffered write support. + bt_block *rootBlock; + sem_id blockSem; + int32 blockVar; + + char ioBuffer[BT_MAX_IO_BUFFER + 9]; + char attrBuffer[BT_MAX_ATTR_BUFFER + 1]; + char pathBuffer[B_PATH_NAME_LENGTH + 1]; +} bt_session_t; + +typedef void (*bt_net_func)(bt_session_t *, unsigned int, int, bt_arg_t *); + +typedef struct dirCommand +{ + unsigned char command; + bt_net_func handler; +} bt_command_t; + +typedef struct btnode +{ + vnode_id vnid; + char name[B_FILE_NAME_LENGTH]; + int refCount; + bool invalid; + struct btnode *next; + struct btnode *prev; + struct btnode *parent; +} bt_node; + +typedef struct fileShare +{ + char path[B_PATH_NAME_LENGTH]; + char name[B_FILE_NAME_LENGTH]; + + bool used; + bool readOnly; + + // What rights does each user have? + bt_user_rights *rights; + int security; + + struct fileShare *next; +} bt_fileShare_t; + +bt_node *rootNode = NULL; + + +int main(int argc, char *argv[]); +void daemonInit(); +bool dateCheck(); +int32 btSendHost(void *data); +int getSharedResources(char *buffer, int bufSize); +void getHostInfo(bt_hostinfo *info); +int getHostUsers(char *buffer); +void startService(); +void endService(int sig); +void restartService(); +void initSessions(); +void initShares(); +void freeFileHandles(); +void freeFileShares(); +void getFileShare(const char *buffer); +void getShareProperty(const char *buffer); +void getGrant(const char *buffer); +void getAuthenticate(const char *buffer); +void addUserRights(char *share, char *user, int rights, bool isGroup); +int getToken(); +int receiveRequest(bt_session_t *session); +void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]); +void launchThread(int client, struct sockaddr_in *addr); +int tooManyConnections(unsigned int s_addr); +void sendErrorToClient(int client, unsigned int xid, int error); +void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command); +int32 requestThread(void *data); + +bt_node *btGetNodeFromVnid(vnode_id vnid); +void btAddHandle(vnode_id dir_vnid, vnode_id file_vnid, char *name); +void btRemoveHandle(vnode_id vnid); +void btPurgeNodes(vnode_id vnid); +void btRemoveNode(bt_node *deadNode); +bool btIsAncestorNode(vnode_id vnid, bt_node *node); +char *btGetLocalFileName(char *path, vnode_id vnid); +bt_node *btFindNode(bt_node *parent, char *fileName); +char *btGetSharePath(char *shareName); +int btGetShareId(char *shareName); +int btGetShareIdByPath(char *path); +void btGetRootPath(vnode_id vnid, char *path); +void btLock(sem_id semaphore, int32 *atomic); +void btUnlock(sem_id semaphore, int32 *atomic); + +int btPreMount(bt_session_t *session, char *shareName); +int btMount(bt_session_t *session, char *shareName, char *user, char *password, vnode_id *vnid); +int btGetFSInfo(char *rootPath, fs_info *fsInfo); +int btLookup(char *pathBuf, vnode_id dir_vnid, char *fileName, vnode_id *file_vnid); +int btStat(char *pathBuf, vnode_id vnid, struct stat *st); +int btReadDir(char *pathBuf, vnode_id dir_vnid, DIR **dir, vnode_id *file_vnid, char *filename, struct stat *st); +int32 btRead(char *pathBuf, vnode_id vnid, off_t pos, int32 len, char *buffer); +int32 btWrite(bt_session_t *session, vnode_id vnid, off_t pos, int32 len, int32 totalLen, char *buffer); +int btCreate(char *pathBuf, vnode_id dir_vnid, char *name, int omode, int perms, vnode_id *file_vnid); +int btTruncate(char *pathBuf, vnode_id vnid, int64 len); +int btCreateDir(char *pathBuf, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, struct stat *st); +int btDeleteDir(char *pathBuf, vnode_id vnid, char *name); +int btRename(char *pathBuf, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName); +int btUnlink(char *pathBuf, vnode_id vnid, char *name); +int btReadLink(char *pathBuf, vnode_id vnid, char *buffer, int length); +int btSymLink(char *pathBuf, vnode_id vnid, char *name, char *dest); +int btWStat(char *pathBuf, vnode_id vnid, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime); +int btReadAttrib(char *pathBuf, vnode_id vnid, char *name, int32 dataType, void *buffer, int32 pos, int32 len); +int btWriteAttrib(char *pathBuf, vnode_id vnid, char *name, int32 dataType, void *buffer, int32 pos, int32 len); +int btReadAttribDir(char *pathBuf, vnode_id vnid, DIR **dir, char *attrName); +int btRemoveAttrib(char *pathBuf, vnode_id vnid, char *name); +int btStatAttrib(char *pathBuf, vnode_id vnid, char *name, struct attr_info *info); +int btReadIndexDir(char *rootPath, DIR **dir, char *indexName); +int btCreateIndex(char *rootPath, char *name, int type, int flags); +int btRemoveIndex(char *rootPath, char *name); +int btStatIndex(char *rootPath, char *name, struct index_info *info); +int btReadQuery(char *rootPath, DIR **dir, char *query, char *fileName, vnode_id *vnid, vnode_id *parent); +int btCommit(bt_session_t *session, vnode_id vnid); + +bt_block *btGetWriteBlock(bt_session_t *session, vnode_id vnid); +void btInsertWriteBlock(bt_session_t *session, bt_block *block); +void btRemoveWriteBlock(bt_session_t *session, bt_block *block); + +void netbtPreMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtPrintJobNew(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtPrintJobData(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtPrintJobCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); +void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); + +bt_session_t sessions[BT_MAX_THREADS]; +bt_fileShare_t fileShares[BT_MAX_FILE_SHARES]; +char tokBuffer[B_PATH_NAME_LENGTH], *tokPtr; +bool running = true; +int server; +unsigned int authServerIP; +thread_id hostThread; +sem_id handleSem; +int32 handleVar; + +bt_command_t dirCommands[] = +{ + { BT_CMD_PREMOUNT, netbtPreMount }, + { BT_CMD_MOUNT, netbtMount }, + { BT_CMD_FSINFO, netbtFSInfo }, + { BT_CMD_LOOKUP, netbtLookup }, + { BT_CMD_STAT, netbtStat }, + { BT_CMD_READDIR, netbtReadDir }, + { BT_CMD_READ, netbtRead }, + { BT_CMD_WRITE, netbtWrite }, + { BT_CMD_CREATE, netbtCreate }, + { BT_CMD_TRUNCATE, netbtTruncate }, + { BT_CMD_MKDIR, netbtCreateDir }, + { BT_CMD_RMDIR, netbtDeleteDir }, + { BT_CMD_RENAME, netbtRename }, + { BT_CMD_UNLINK, netbtUnlink }, + { BT_CMD_READLINK, netbtReadLink }, + { BT_CMD_SYMLINK, netbtSymLink }, + { BT_CMD_WSTAT, netbtWStat }, + { BT_CMD_READATTRIB, netbtReadAttrib }, + { BT_CMD_WRITEATTRIB, netbtWriteAttrib }, + { BT_CMD_READATTRIBDIR, netbtReadAttribDir }, + { BT_CMD_REMOVEATTRIB, netbtRemoveAttrib }, + { BT_CMD_STATATTRIB, netbtStatAttrib }, + { BT_CMD_READINDEXDIR, netbtReadIndexDir }, + { BT_CMD_CREATEINDEX, netbtCreateIndex }, + { BT_CMD_REMOVEINDEX, netbtRemoveIndex }, + { BT_CMD_STATINDEX, netbtStatIndex }, + { BT_CMD_READQUERY, netbtReadQuery }, + { BT_CMD_COMMIT, netbtCommit }, + { BT_CMD_PRINTJOB_NEW, netbtPrintJobNew }, + { BT_CMD_PRINTJOB_DATA, netbtPrintJobData }, + { BT_CMD_PRINTJOB_COMMIT, netbtPrintJobCommit }, + { BT_CMD_AUTHENTICATE, netbtAuthenticate }, + { BT_CMD_QUIT, netbtQuit }, + { 0, NULL } +}; + +char *keywords[] = +{ + "share", + "as", + "set", + "read", + "write", + "read-write", + "promiscuous", + "on", + "to", + "authenticate", + "with", + "group", + "printer", + "print", + "is", + "spooled", + "device", + "type", + NULL +}; + +/*---------------------------------------------------------------- +class BeServedServer : public BApplication +{ + thread_id appThread; + bool running; + + public: + BeServedServer(const char *signature); + + virtual void ReadyToRun(); + virtual bool QuitRequested(); +}; + +BeServedServer::BeServedServer(const char *signature) + : BApplication(signature) +{ +} + +void BeServedServer::ReadyToRun() +{ + running = true; + appThread = spawn_thread(appMain, BT_MAIN_NAME, B_NORMAL_PRIORITY, this); + resume_thread(appThread); +} + +bool BeServedServer::QuitRequested() +{ + status_t result; + + if (!BApplication::QuitRequested()) + return false; + + running = false; + wait_for_thread(appThread, &result); + return true; +} + +int main(int argc, char *argv[]) +{ + BeServedServer app(BT_SIGNATURE); + app.Run(); + return 0; +} +----------------------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + daemonInit(); + + initSessions(); + initShares(); + signal(SIGINT, endService); + signal(SIGTERM, endService); + signal(SIGHUP, restartService); + signal(SIGPIPE, SIG_IGN); + + if ((handleSem = create_sem(0, "File Handle Semaphore")) > B_OK) + { + hostThread = spawn_thread(btSendHost, BT_HOST_THREAD_NAME, B_NORMAL_PRIORITY, 0); + resume_thread(hostThread); + + // Run the daemon. We will not return until the service is being stopped. + startService(); + + if (hostThread > 0) + kill_thread(hostThread); + + delete_sem(handleSem); + } + + return 0; +} + +bool dateCheck() +{ + struct stat st; + time_t curTime; + + time(&curTime); + if (curTime > 1012537700) + return false; + + if (stat("/boot/home/config/servers/beserved_server", &st) == 0) + if (curTime < st.st_ctime || curTime > st.st_ctime + 7776000) + return false; + + return true; +} + +void daemonInit() +{ + int i; + + // Cause the parent task to terminate, freeing the terminal. + if (fork() != 0) + exit(0); + + // In the child process, become the session leader. + setsid(); + + // Now fork again, causing the first child to exit, since the session + // leader can be assigned a controlling terminal under SVR4. + signal(SIGHUP, SIG_IGN); + if (fork() != 0) + exit(0); + + // Change to the root directory, since if we hold on to a working + // folder that was in a mounted file system, that file system cannot + // be unmounted. + chdir("/"); + + // Reset the file creation mask to zero to eliminate the inherited value. + umask(0); + + // Close open file descriptors. Since we can't know how many of a + // potentially unlimited value can be open, just close the first 64 + // and assume that will be enough. + for (i = 0; i < 64; i++) + close(i); + + // Open the syslog. + openlog("beserved_server", LOG_PID, LOG_DAEMON); +} + +void restartService() +{ + bt_fileShare_t *oldShares; + int i; + + // Delay all mounting and other file system operations. + btLock(handleSem, &handleVar); + + // Copy existing share data. + oldShares = (bt_fileShare_t *) malloc(sizeof(bt_fileShare_t) * BT_MAX_FILE_SHARES); + if (oldShares) + { + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + memcpy(&oldShares[i], &fileShares[i], sizeof(bt_fileShare_t)); + + // Reload the share data. + initShares(); + + // Now loop through the old file shares. For each one, check if the same + // path exists in the new shares. + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (oldShares[i].used) + { + int share = btGetShareIdByPath(oldShares[i].path); + if (share == -1) + { + for (i = 0; i < BT_MAX_THREADS; i++) + if (sessions[i].share == i) + sessions[i].killed = true; + } + else if (share != i) + for (i = 0; i < BT_MAX_THREADS; i++) + if (sessions[i].share == i) + sessions[i].share = share; + } + + free(oldShares); + } + + // Resume normal operation. + btUnlock(handleSem, &handleVar); +} + +int32 btSendHost(void *data) +{ + bt_request request; + bt_hostinfo info; + struct sockaddr_in serverAddr, clientAddr; + char buffer[4096]; + int server, addrLen, bufLen, replyLen; + + buffer[0] = 0; + bufLen = sizeof(buffer); + + server = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (server == INVALID_SOCKET) + return -1; + + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(BT_QUERYHOST_PORT); + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Bind that socket to the address constructed above. + if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return -1; + + while (running) + { + addrLen = sizeof(struct sockaddr_in); + replyLen = 0; + if (recvfrom(server, (char *) &request, sizeof(request), 0, (struct sockaddr *) &clientAddr, &addrLen) <= 0) + continue; + + switch (request.command) + { + case BT_REQ_HOST_PROBE: + gethostname(buffer, bufLen); + break; + + case BT_REQ_SHARE_PROBE: + replyLen = getSharedResources(buffer, sizeof(buffer)); + break; + + case BT_REQ_HOST_INFO: + getHostInfo(&info); + memcpy(buffer, &info, sizeof(bt_hostinfo)); + replyLen = sizeof(bt_hostinfo); + break; + + case BT_REQ_HOST_USERS: + replyLen = getHostUsers(buffer); + break; + + case BT_REQ_AUTH_TYPES: + break; + } + + // If no reply length has been specified, calculate it now by taking the + // length of the buffer. + if (replyLen == 0) + replyLen = strlen(buffer); + + sendto(server, buffer, replyLen, 0, (struct sockaddr *) &clientAddr, addrLen); + } + + // Close the socket. Technically, I believe we should call shutdown() + // first, but the BeOS header file socket.h indicates that this + // function is not currently working. It is present but may not have + // any effect. + shutdown(server, 2); + closesocket(server); + return 0; +} + +// getSharedResources() +// +int getSharedResources(char *buffer, int bufSize) +{ + bt_resource resource; + int i, bufPos = 0; + + // If the supplied buffer can't hold at least two resource structures, one + // for a shared resource and one to terminate the list, then don't bother + // building the list. + if (bufSize < 2 * sizeof(bt_resource)) + return 0; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + { + // If this is the last resource structure that will fit in the + // buffer, then don't add any more into the list. + if (bufPos + sizeof(bt_resource) >= bufSize) + break; + + // Fill out the resource structure. + resource.type = B_HOST_TO_LENDIAN_INT32(BT_SHARED_FOLDER); + strcpy(resource.name, fileShares[i].name); + + // Copy the resource structure into the buffer at the current offset. + memcpy(buffer + bufPos, &resource, sizeof(bt_resource)); + bufPos += sizeof(bt_resource); + } + + // Copy the null terminating structure. + resource.type = B_HOST_TO_LENDIAN_INT32(BT_SHARED_NULL); + resource.name[0] = 0; + memcpy(buffer + bufPos, &resource, sizeof(bt_resource)); + bufPos += sizeof(bt_resource); + + return bufPos; +} + +// getHostInfo() +// +void getHostInfo(bt_hostinfo *info) +{ + system_info sysinfo; + struct utsname uts; + char buf[100]; + int i; + + struct cpuMap + { + int cpuType; + char *cpuName; + } cpuList[] = + { + { B_CPU_PPC_601, "PowerPC 601" }, + { B_CPU_PPC_603, "PowerPC 603" }, + { B_CPU_PPC_603e, "PowerPC 603e" }, + { B_CPU_PPC_604, "PowerPC 604" }, + { B_CPU_PPC_604e, "PowerPC 604e" }, + { B_CPU_PPC_750, "PowerPC 750" }, + { B_CPU_PPC_686, "PowerPC 686" }, + + { B_CPU_INTEL_X86, "Intel 80x86" }, + { B_CPU_INTEL_PENTIUM, "Intel Pentium" }, + { B_CPU_INTEL_PENTIUM75, "Intel Pentium" }, + { B_CPU_INTEL_PENTIUM_486_OVERDRIVE, "Intel 486 Overdrive" }, + { B_CPU_INTEL_PENTIUM_MMX, "Intel Pentium MMX" }, + { B_CPU_INTEL_PENTIUM_MMX_MODEL_4, "Intel Pentium MMX" }, + { B_CPU_INTEL_PENTIUM_MMX_MODEL_8, "Intel Pentium MMX" }, + { B_CPU_INTEL_PENTIUM75_486_OVERDRIVE, "Intel 486 Overdrive" }, + { B_CPU_INTEL_PENTIUM_PRO, "Intel Pentium Pro" }, + { B_CPU_INTEL_PENTIUM_II, "Intel Pentium II" }, + { B_CPU_INTEL_PENTIUM_II_MODEL_3, "Intel Pentium II" }, + { B_CPU_INTEL_PENTIUM_II_MODEL_5, "Intel Pentium II" }, + { B_CPU_INTEL_CELERON, "Intel Celeron" }, + { B_CPU_INTEL_PENTIUM_III, "Intel Pentium III" }, + + { B_CPU_AMD_X86, "AMD x86" }, + { B_CPU_AMD_K5_MODEL0, "AMD K5" }, + { B_CPU_AMD_K5_MODEL1, "AMD K5" }, + { B_CPU_AMD_K5_MODEL2, "AMD K5" }, + { B_CPU_AMD_K5_MODEL3, "AMD K5" }, + { B_CPU_AMD_K6_MODEL6, "AMD K6" }, + { B_CPU_AMD_K6_MODEL7, "AMD K6" }, + { B_CPU_AMD_K6_MODEL8, "AMD K6" }, + { B_CPU_AMD_K6_2, "AMD K6-2" }, + { B_CPU_AMD_K6_MODEL9, "AMD K6" }, + { B_CPU_AMD_K6_III, "AMD K6-3" }, + { B_CPU_AMD_ATHLON_MODEL1, "AMD Athlon" }, + + { B_CPU_CYRIX_X86, "Cyrix x86" }, + { B_CPU_CYRIX_GXm, "Cyrix GXm" }, + { B_CPU_CYRIX_6x86MX, "Cyrix 6x86MX" }, + + { B_CPU_IDT_X86, "IDT x86" }, + { B_CPU_IDT_WINCHIP_C6, "IDT WinChip C6" }, + { B_CPU_IDT_WINCHIP_2, "IDT WinChip 2" }, + + { B_CPU_RISE_X86, "Rise x86" }, + { B_CPU_RISE_mP6, "Rise mP6" }, + + { 0, NULL } + }; + + uname(&uts); + get_system_info(&sysinfo); + + strcpy(info->system, uts.sysname); + strcat(info->system, " "); + strcat(info->system, uts.release); + strcpy(info->beServed, "BeServed 1.2.5"); + + info->cpus = B_HOST_TO_LENDIAN_INT32(sysinfo.cpu_count); + info->maxConnections = B_HOST_TO_LENDIAN_INT32(BT_MAX_THREADS); + + strcpy(info->platform, "Unknown"); + for (i = 0; cpuList[i].cpuType; i++) + if (cpuList[i].cpuType == sysinfo.cpu_type) + { + strcpy(info->platform, cpuList[i].cpuName); + break; + } + + sprintf(buf, " at %ldMHz", (long) (sysinfo.cpu_clock_speed / 1000000)); + strcat(info->platform, buf); + + info->connections = 0; + for (i = 0; i < BT_MAX_THREADS; i++) + if (sessions[i].socket != INVALID_SOCKET) + info->connections++; + + info->connections = B_HOST_TO_LENDIAN_INT32(info->connections); +} + +// getHostUsers() +// +int getHostUsers(char *buffer) +{ + char addr[20]; + int i, len, bufSize; + + // Initialize the buffer to be empty. + buffer[0] = 0; + bufSize = 0; + + for (i = 0; i < BT_MAX_THREADS; i++) + if (sessions[i].socket != INVALID_SOCKET) + { + uint8 *s_addr = (uint8 *) sessions[i].s_addr; + sprintf(addr, "%d.%d.%d.%d", s_addr[0], s_addr[1], s_addr[2], s_addr[3]); + len = strlen(buffer); + strcpy(&buffer[len > 0 ? len + 1 : 0], addr); + bufSize += len + 1; + } + + buffer[bufSize++] = 0; + return bufSize; +} + +// initSessions() +// +void initSessions() +{ + int i; + + for (i = 0; i < BT_MAX_THREADS; i++) + { + sessions[i].socket = INVALID_SOCKET; + sessions[i].handlerID = 0; + sessions[i].killed = false; + sessions[i].rights = 0; + } +} + +void initShares() +{ + FILE *fp; + char path[B_PATH_NAME_LENGTH], buffer[512]; + int i, length; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + { + fileShares[i].name[0] = 0; + fileShares[i].path[0] = 0; + fileShares[i].used = false; + fileShares[i].readOnly = true; + fileShares[i].security = BT_AUTH_NONE; + fileShares[i].rights = NULL; + fileShares[i].next = NULL; + } + + find_directory(B_COMMON_SETTINGS_DIRECTORY, 0, false, path, sizeof(path)); + strcat(path, "/BeServed-Settings"); + + fp = fopen(path, "r"); + if (fp) + { + while (fgets(buffer, sizeof(buffer) - 1, fp)) + { + length = strlen(buffer); + if (length <= 1 || buffer[0] == '#') + continue; + + if (buffer[length - 1] == '\n') + buffer[--length] = 0; + + if (strncmp(buffer, "share ", 6) == 0) + getFileShare(buffer); + else if (strncmp(buffer, "set ", 4) == 0) + getShareProperty(buffer); + else if (strncmp(buffer, "grant ", 6) == 0) + getGrant(buffer); + else if (strncmp(buffer, "authenticate ", 13) == 0) + getAuthenticate(buffer); + } + + fclose(fp); + } +} + +void getFileShare(const char *buffer) +{ + struct stat st; + char path[B_PATH_NAME_LENGTH], share[MAX_NAME_LENGTH + 1], *folder; + int i, tok; + + // Skip over SHARE command. + tokPtr = (char *) buffer + (6 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(path, tokBuffer); + tok = getToken(); + if (tok != BT_TOKEN_AS) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + + // Now verify that the share name specified has not already been + // used to share another path. + folder = btGetSharePath(share); + if (folder) + { + syslog(LOG_WARNING, "%s already defined as %s\n", share, folder); + return; + } + + // Check the path to ensure its validity. + if (stat(path, &st) != 0) + return; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (!fileShares[i].used) + { + syslog(LOG_INFO, "Defining %s as %s\n", share, path); + strcpy(fileShares[i].name, share); + strcpy(fileShares[i].path, path); + fileShares[i].used = true; + return; + } + + syslog(LOG_WARNING, "Share %s could not be defined (too many shares)\n", share); +} + +void getShareProperty(const char *buffer) +{ + char share[B_FILE_NAME_LENGTH + 1]; + int tok, shareId; + + // Skip over SET command. + tokPtr = (char *) buffer + (4 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + + // Get the index of the share referred to. If the named share cannot be + // found, then abort. + shareId = btGetShareId(share); + if (shareId < 0) + return; + + tok = getToken(); + if (tok == BT_TOKEN_READWRITE) + { + fileShares[shareId].readOnly = false; + syslog(LOG_INFO, "%s permits writing\n", share); + } +} + +void getGrant(const char *buffer) +{ + char share[MAX_NAME_LENGTH + 1]; + int tok, rights; + bool isGroup = false; + + // Skip over GRANT command. + tokPtr = (char *) buffer + (6 * sizeof(char)); + rights = 0; + + do + { + tok = getToken(); + if (tok == BT_TOKEN_READ) + { + rights |= BT_RIGHTS_READ; + tok = getToken(); + } + else if (tok == BT_TOKEN_WRITE) + { + rights |= BT_RIGHTS_WRITE; + tok = getToken(); + } + } while (tok == BT_TOKEN_COMMA); + + if (tok != BT_TOKEN_ON) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + strcpy(share, tokBuffer); + tok = getToken(); + if (tok != BT_TOKEN_TO) + return; + + tok = getToken(); + if (tok == BT_TOKEN_GROUP) + { + isGroup = true; + tok = getToken(); + } + + if (tok != BT_TOKEN_STRING) + return; + + addUserRights(share, tokBuffer, rights, isGroup); +} + +void getAuthenticate(const char *buffer) +{ + struct hostent *ent; + int i, tok; + + // Skip over AUTHENTICATE command. + tokPtr = (char *) buffer + (13 * sizeof(char)); + + tok = getToken(); + if (tok != BT_TOKEN_WITH) + return; + + tok = getToken(); + if (tok != BT_TOKEN_STRING) + return; + + // Look up address for given host. + ent = gethostbyname(tokBuffer); + if (ent == NULL) + { + syslog(LOG_ERR, "Authentication server %s is unavailable.\n", tokBuffer); + endService(0); + } + + authServerIP = ntohl(*((unsigned int *) ent->h_addr)); + + // Make all file shares use BeSure authentication. + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + fileShares[i].security = BT_AUTH_BESURE; + + syslog(LOG_INFO, "Using authentication server at %s\n", tokBuffer); +} + +void addUserRights(char *share, char *user, int rights, bool isGroup) +{ + bt_user_rights *ur; + int shareId; + + shareId = btGetShareId(share); + if (shareId < 0) + return; + + ur = (bt_user_rights *) malloc(sizeof(bt_user_rights)); + if (ur) + { + ur->user = (char *) malloc(strlen(user) + 1); + if (ur->user) + { + strcpy(ur->user, user); + ur->rights = rights; + ur->isGroup = isGroup; + ur->next = fileShares[shareId].rights; + fileShares[shareId].rights = ur; + } + else + free(ur); + } +} + +int getToken() +{ + bool quoted = false; + + tokBuffer[0] = 0; + while (*tokPtr && iswhite(*tokPtr)) + tokPtr++; + + if (*tokPtr == ',') + { + tokPtr++; + return BT_TOKEN_COMMA; + } + else if (*tokPtr == '\"') + { + quoted = true; + tokPtr++; + } + + if (isalnum(*tokPtr) || *tokPtr == '/') + { + int i = 0; + while (isalnum(*tokPtr) || isValid(*tokPtr) || (quoted && *tokPtr == ' ')) + if (i < B_PATH_NAME_LENGTH) + tokBuffer[i++] = *tokPtr++; + else + tokPtr++; + + tokBuffer[i] = 0; + + if (!quoted) + for (i = 0; keywords[i]; i++) + if (strcasecmp(tokBuffer, keywords[i]) == 0) + return ++i; + + if (quoted) + if (*tokPtr != '\"') + return BT_TOKEN_ERROR; + else + tokPtr++; + + return BT_TOKEN_STRING; + } + + return BT_TOKEN_ERROR; +} + +void startService() +{ + struct sockaddr_in serverAddr, clientAddr; + int client, addrLen; + int flags; + + // Store the length of the socket addressing structure for accept(). + addrLen = sizeof(struct sockaddr_in); + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(BT_TCPIP_PORT); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Create a new socket to receive incoming requests. + server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (server == INVALID_SOCKET) + return; + + // Set the socket option to reuse the current address in case it was + // in use by a prior version of the service that has not yet relinquished + // the socket. + flags = 1; + setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); + + // Bind that socket to the address constructed above. + if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return; + + // Listen for incoming connections. + if (listen(server, 5)) + return; + + // Continually accept incoming connections. When one is found, + // fire off a handler thread to accept commands. + while (running) + { + client = accept(server, (struct sockaddr *) &clientAddr, &addrLen); + if (client != INVALID_SOCKET) + launchThread(client, &clientAddr); + } + + // Close the socket. Technically, I believe we should call shutdown() + // first, but the BeOS header file socket.h indicates that this + // function is not currently working. It is present but may not have + // any effect. + shutdown(server, 2); + closesocket(server); + server = INVALID_SOCKET; +} + +void endService(int sig) +{ + // Close the syslog. + closelog(); + + if (hostThread > 0) + kill_thread(hostThread); + + if (handleSem > 0) + delete_sem(handleSem); + + freeFileHandles(); + freeFileShares(); + + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + exit(0); +} + +// freeFileHandles() +// +void freeFileHandles() +{ + bt_node *nextNode, *curNode = rootNode; + + while (curNode) + { + nextNode = curNode->next; + free(curNode); + curNode = nextNode; + } +} + +// freeFileShares() +// +void freeFileShares() +{ + bt_user_rights *ur, *nextUr; + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + for (ur = fileShares[i].rights; ur; ) + { + nextUr = ur->next; + if (ur->user) + free(ur->user); + + free(ur); + ur = nextUr; + } +} + +// launchThread() +// +void launchThread(int client, struct sockaddr_in *addr) +{ + int i, retry, found; + + // We need to find an available session for this connection. We don't + // want to create threads willy nilly until we bring down the OS, so we + // establish a pool of available sessions (threads) from which we must + // allocate with every request. + found = FALSE; + for (retry = 0; retry < BT_MAX_RETRIES && !found; retry++) + { + for (i = 0; i < BT_MAX_THREADS; i++) + if (sessions[i].socket == INVALID_SOCKET) + { + found = TRUE; + sessions[i].socket = client; + sessions[i].s_addr = addr->sin_addr.s_addr; + sessions[i].handlerID = + spawn_thread(requestThread, BT_THREAD_NAME, B_NORMAL_PRIORITY, &sessions[i]); + resume_thread(sessions[i].handlerID); + break; + } + + if (!found) + snooze(100000); + } + + if (!found) + { + sendErrorToClient(client, 0, EBUSY); + shutdown(client, 2); + closesocket(client); + } +} + +int32 requestThread(void *data) +{ + bt_session_t *session = (bt_session_t *) data; +// int flags; + + if (!session) + return 0; + + // Ensure that this connection remains alive. If a periodic message (handled by the OS) + // fails, then blocked socket calls are interrupted and return with a ESIGPIPE error. +// flags = 1; +// setsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags)); + + if ((session->blockSem = create_sem(0, "Gathered Write Semaphore")) > B_OK) + { + session->rootBlock = NULL; + while (!session->killed && receiveRequest(session)); + delete_sem(session->blockSem); + } + + shutdown(session->socket, 2); + closesocket(session->socket); + session->socket = INVALID_SOCKET; + return 0; +} + +int receiveRequest(bt_session_t *session) +{ + bt_inPacket packet; + char signature[20], *buffer; + unsigned char command; + int client, sigLen; + int32 length; + + client = session->socket; + + // Read the BeTalk RPC header. + sigLen = strlen(BT_RPC_SIGNATURE); + if (btRecvMsg(client, signature, sigLen, 0) == -1) + return 0; +// recv(client, &verHi, sizeof(verHi), 0); +// recv(client, &verLo, sizeof(verLo), 0); + + signature[sigLen] = 0; + if (strcmp(signature, BT_RPC_SIGNATURE)) + return 0; + + // Read in the rest of the packet. + if (btRecvMsg(client, &length, sizeof(int32), 0) == -1) + return 0; + + length = B_LENDIAN_TO_HOST_INT32(length); + if (length == 0 || length > BT_RPC_MAX_PACKET_SIZE) + return 0; + + buffer = (char *) malloc(length + 1); + if (!buffer) + return 0; + + if (btRecvMsg(client, buffer, length, 0) == -1) + { + free(buffer); + return 0; + } + + buffer[length] = 0; + packet.buffer = buffer; + packet.length = length; + packet.offset = 0; + + // Read the transmission ID and command. + command = btRPCGetChar(&packet); + getArguments(session, &packet, command); + free(buffer); + return (command != BT_CMD_QUIT && command != BT_CMD_PREMOUNT); +} + +void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command) +{ + bt_arg_t args[MAX_COMMAND_ARGS]; + int i, client; + bool error; + unsigned char argc, terminator; + int32 xid; + + error = false; + client = session->socket; + argc = btRPCGetChar(packet); + if (argc > MAX_COMMAND_ARGS) + return; + + for (i = 0; i < argc && !error; i++) + { + args[i].type = btRPCGetInt32(packet); + args[i].data = btRPCGetNewString(packet); + if (args[i].data == NULL) + error = true; + } + + if (!error) + { + xid = btRPCGetInt32(packet); + terminator = btRPCGetChar(packet); + if (terminator == BT_CMD_TERMINATOR) + handleRequest(session, xid, command, argc, args); + } + else + sendErrorToClient(session->socket, 0, EINVAL); + + while (--i >= 0) + free(args[i].data); +} + +void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]) +{ + int i; + + for (i = 0; dirCommands[i].handler; i++) + if (command == dirCommands[i].command) + { + (*dirCommands[i].handler)(session, xid, argc, argv); + return; + } + + sendErrorToClient(session->socket, xid, EINVAL); +} + +void sendErrorToClient(int client, unsigned int xid, int error) +{ + bt_outPacket packet; + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); +} + +int btRecvMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesRead = 0; + do + { + int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags); + if (bytes == -1) + return -1; + + bytesRead += bytes; + } while (bytesRead < dataLen); + + return bytesRead; +} + +// btRecv() +// +int btRecv(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = recv(sock, data, dataLen, flags); + if (bytes == 0) + return -1; + else if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +int btSendMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesSent = 0; + do + { + int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags); + if (bytes == -1) + return -1; + + bytesSent += bytes; + } while (bytesSent < dataLen); + + return bytesSent; +} + +// btSend() +// +int btSend(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = send(sock, data, dataLen, flags); + if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error) +{ + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + return; + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + btRPCPutInt32(packet, xid); + btRPCPutInt32(packet, 0); + btRPCPutInt32(packet, error); +} + +void btRPCSendAck(int client, bt_outPacket *packet) +{ + if (packet) + if (packet->buffer) + { + *(int32 *)(&packet->buffer[9]) = packet->length - 13; + btSendMsg(client, packet->buffer, packet->length, 0); + free(packet->buffer); + } +} + +unsigned char btRPCGetChar(bt_inPacket *packet) +{ + unsigned char value; + + if (packet->offset < packet->length) + value = (unsigned char) packet->buffer[packet->offset]; + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + if (bytes > 0) + memcpy(str, &packet->buffer[packet->offset], bytes); + + str[bytes] = 0; + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return ERANGE; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) + return ERANGE; + + if (length < bytes) + return ERANGE; + + if (bytes > 0) + memcpy(buffer, &packet->buffer[packet->offset], bytes); + + packet->offset += bytes; + return bytes; +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +int btRPCGetStat(bt_inPacket *packet, struct stat *st) +{ + st->st_dev = 0; + st->st_nlink = btRPCGetInt32(packet); + st->st_uid = btRPCGetInt32(packet); + st->st_gid = btRPCGetInt32(packet); + st->st_size = btRPCGetInt64(packet); + st->st_blksize = btRPCGetInt32(packet); + st->st_rdev = btRPCGetInt32(packet); + st->st_ino = btRPCGetInt64(packet); + st->st_mode = btRPCGetInt32(packet); + st->st_atime = btRPCGetInt32(packet); + st->st_mtime = btRPCGetInt32(packet); + st->st_ctime = btRPCGetInt32(packet); +} + +void btRPCPutStat(bt_outPacket *packet, struct stat *st) +{ + if (packet && st) + { + btRPCPutInt32(packet, (int) st->st_nlink); + btRPCPutInt32(packet, (int) st->st_uid); + btRPCPutInt32(packet, (int) st->st_gid); + btRPCPutInt64(packet, (int64) st->st_size); + btRPCPutInt32(packet, (int) st->st_blksize); + btRPCPutInt32(packet, (int) st->st_rdev); + btRPCPutInt64(packet, (int64) st->st_ino); + btRPCPutInt32(packet, (int) st->st_mode); + btRPCPutInt32(packet, (int) st->st_atime); + btRPCPutInt32(packet, (int) st->st_mtime); + btRPCPutInt32(packet, (int) st->st_ctime); + } +} + +//////////////////////////////////////////////////////////////////// + +bt_node *btGetNodeFromVnid(vnode_id vnid) +{ + register bt_node *curNode = rootNode; + + while (curNode && curNode->vnid != vnid) + curNode = curNode->next; + + return curNode; +} + +// btAddHandle() +// +void btAddHandle(vnode_id dir_vnid, vnode_id file_vnid, char *name) +{ + bt_node *curNode, *dirNode; + + // We don't store the references to the current and the parent directory. + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + return; + + btLock(handleSem, &handleVar); + + // Obtain the parent node. If no parent vnid is provided, then this must be + // the root node. The parent of the root node is NULL, but it should be the + // only node for which this is true. + if (dir_vnid) + dirNode = btGetNodeFromVnid(dir_vnid); + else + dirNode = NULL; + + // If a node already exists with the given vnid, then it is either a symbolic + // link or an attempt to add the same node again, such as when mounting or + // walking a directory tree. If we find a matching vnid whose parent directory + // and name also match, this is a duplicate and can be ignored. + curNode = btGetNodeFromVnid(file_vnid); + if (curNode) + if (curNode->parent == dirNode && strcmp(curNode->name, name) == 0) + { + btUnlock(handleSem, &handleVar); + return; + } + + // Allocate a new node. + curNode = (bt_node *) malloc(sizeof(bt_node)); + if (curNode == NULL) + { + btUnlock(handleSem, &handleVar); + return; + } + + // Copy over the name, vnid, and parent node. Obtaining the parent + // node requires scanning the list. + strcpy(curNode->name, name); + curNode->refCount = 0; + curNode->invalid = false; + curNode->vnid = file_vnid; + curNode->parent = dirNode; + + // Add the node to the head of the list. + curNode->next = rootNode; + curNode->prev = NULL; + if (rootNode) + rootNode->prev = curNode; + rootNode = curNode; + + btUnlock(handleSem, &handleVar); +} + +// btRemoveHandle() +// +void btRemoveHandle(vnode_id vnid) +{ + bt_node *deadNode; + + btLock(handleSem, &handleVar); + + // Obtain the node in question. If no such node exists, then we + // probably have a bad handle. + deadNode = btGetNodeFromVnid(vnid); + btRemoveNode(deadNode); + + btUnlock(handleSem, &handleVar); +} + +// btRemoveNode() +// +void btRemoveNode(bt_node *deadNode) +{ + if (deadNode) + { + // If this node is the root node, then we need to reset the root node + // to the next node in the list. + if (deadNode == rootNode) + rootNode = deadNode->next; + + // Make this entry's predecessor point to its successor. + if (deadNode->prev) + deadNode->prev->next = deadNode->next; + + // Make this entry's successor point to its predecessor. + if (deadNode->next) + deadNode->next->prev = deadNode->prev; + + // Now deallocate this node. + free(deadNode); + } +} + +// btPurgeNodes() +// +void btPurgeNodes(vnode_id vnid) +{ + bt_node *curNode, *nextNode; + + btLock(handleSem, &handleVar); + + // First loop through, marking this node and all its children as invalid. + curNode = rootNode; + while (curNode) + { + if (curNode->vnid == vnid || btIsAncestorNode(vnid, curNode)) + curNode->invalid = true; + + curNode = curNode->next; + } + + // Now loop through again, removing all invalid nodes. This prevents removing + // a parent node and all its children being orphaned (with invalid pointers + // back to the destroyed parent). + curNode = rootNode; + while (curNode) + if (curNode->invalid) + { + nextNode = curNode->next; + btRemoveNode(curNode); + curNode = nextNode; + } + else + curNode = curNode->next; + + btUnlock(handleSem, &handleVar); +} + +// btIsAncestorNode() +// +bool btIsAncestorNode(vnode_id vnid, bt_node *node) +{ + bt_node *curNode = node->parent; + + while (curNode) + { + if (curNode->vnid == vnid) + return true; + + curNode = curNode->parent; + } + + return false; +} + +// btGetLocalFileName() +// +char *btGetLocalFileName(char *path, vnode_id vnid) +{ + bt_node *node, *nodeStack[100]; + int stackSize; + + path[0] = 0; + stackSize = 1; + + btLock(handleSem, &handleVar); + + node = btGetNodeFromVnid(vnid); + if (node == NULL) + { + btUnlock(handleSem, &handleVar); + return NULL; + } + + nodeStack[0] = node; + while ((node = node->parent) != NULL) + nodeStack[stackSize++] = node; + + while (--stackSize >= 0) + { + strcat(path, nodeStack[stackSize]->name); + if (stackSize) + strcat(path, "/"); + } + + btUnlock(handleSem, &handleVar); + return path; +} + +bt_node *btFindNode(bt_node *parent, char *fileName) +{ + bt_node *node; + + btLock(handleSem, &handleVar); + + node = rootNode; + while (node) + { + if (node->parent == parent) + if (strcmp(node->name, fileName) == 0) + break; + + node = node->next; + } + + btUnlock(handleSem, &handleVar); + return node; +} + +char *btGetSharePath(char *shareName) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (strcasecmp(fileShares[i].name, shareName) == 0) + return fileShares[i].path; + + return NULL; +} + +int btGetShareId(char *shareName) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (strcasecmp(fileShares[i].name, shareName) == 0) + return i; + + return -1; +} + +int btGetShareIdByPath(char *path) +{ + int i; + + for (i = 0; i < BT_MAX_FILE_SHARES; i++) + if (fileShares[i].used) + if (strcmp(fileShares[i].path, path) == 0) + return i; + + return -1; +} + +// btGetRootPath() +// +void btGetRootPath(vnode_id vnid, char *path) +{ + bt_node *curNode; + + btLock(handleSem, &handleVar); + + curNode = btGetNodeFromVnid(vnid); + while (curNode && curNode->parent) + curNode = curNode->parent; + + if (curNode) + strcpy(path, curNode->name); + else + path[0] = 0; + + btUnlock(handleSem, &handleVar); +} + +void btLock(sem_id semaphore, int32 *atomic) +{ + int32 previous = atomic_add(atomic, 1); + if (previous >= 1) + while (acquire_sem(semaphore) == B_INTERRUPTED); +} + +void btUnlock(sem_id semaphore, int32 *atomic) +{ + int32 previous = atomic_add(atomic, -1); + if (previous > 1) + release_sem(semaphore); +} + +//////////////////////////////////////////////////////////////////// +/* +void btNotifyListeners(char *shareName) +{ + struct sockaddr_in toAddr, fromAddr; + int i; + + for (i = 0; i < BT_MAX_THREADS; i++) + if (strcasecmp(sessions[i].share, shareName) == 0) + { + memset(&toAddr, 0, sizeof(toAddr)); + toAddr.sin_port = htons(BT_NODE_MONITOR_PORT); + toAddr.sin_family = AF_INET; + toAddr.sin_addr.s_addr = sessions[i].s_addr; + + sendto(sock, packet, sizeof(packet), 0, &fromAddr, sizeof(fromAddr)); + } +} +*/ +//////////////////////////////////////////////////////////////////// + +int btPreMount(bt_session_t *session, char *shareName) +{ + // Look for the specified share name. If it can't be found, it must no longer be + // shared on this host. + int shareId = btGetShareId(shareName); + if (shareId < 0) + return ENOENT; + + return fileShares[shareId].security; +} + +int btMount(bt_session_t *session, char *shareName, char *user, char *password, vnode_id *vnid) +{ + bt_user_rights *ur; + struct stat st; + char *path, *groups[MAX_GROUPS_PER_USER]; + int i, shareId; + bool authenticated = false; + + // Initialize the groups array. We may need to release the memory later. + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + groups[i] = NULL; + + // Look for the specified share name. If it can't be found, it must no longer be + // shared on this host. + shareId = btGetShareId(shareName); + if (shareId < 0) + return ENOENT; + + if (fileShares[shareId].security != BT_AUTH_NONE) + { + // Authenticate the user with name/password + authenticated = authenticateUser(user, password); + if (!authenticated) + return EACCES; + + // Does the authenticated user have any rights on this file share? + session->rights = 0; + for (ur = fileShares[shareId].rights; ur; ur = ur->next) + if (!ur->isGroup && strcasecmp(ur->user, user) == 0) + session->rights |= ur->rights; + + // Does the authenticated user belong to any groups that have any rights on this + // file share? + getUserGroups(user, groups); + for (ur = fileShares[shareId].rights; ur; ur = ur->next) + if (ur->isGroup) + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + if (groups[i] && strcasecmp(ur->user, groups[i]) == 0) + { + session->rights |= ur->rights; + break; + } + + // Free the memory occupied by the group list. + for (i = 0; i < MAX_GROUPS_PER_USER; i++) + if (groups[i]) + free(groups[i]); + + // If no rights have been granted, deny access. + if (session->rights == 0) + return EACCES; + + // If write access has been globally disabled, this user's rights must be + // correspondingly synchronized. + if (fileShares[shareId].readOnly) + session->rights = BT_RIGHTS_READ; + } + else + session->rights = fileShares[shareId].readOnly + ? BT_RIGHTS_READ + : BT_RIGHTS_READ | BT_RIGHTS_WRITE; + + // Make sure the folder we want to share still exists. + path = fileShares[shareId].path; + if (stat(path, &st) != 0) + return ENOENT; + + // Make sure it really is a folder and not a file. + if (!S_ISDIR(st.st_mode)) + return EACCES; + + *vnid = st.st_ino; + btAddHandle(0, *vnid, path); + return B_OK; +} + +int btGetFSInfo(char *rootPath, fs_info *fsInfo) +{ + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + if (fs_stat_dev(device, fsInfo) != 0) + return errno; + + return B_OK; +} + +int btLookup(char *pathBuf, vnode_id dir_vnid, char *fileName, vnode_id *file_vnid) +{ + bt_node *dnode, *fnode; + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + + *file_vnid = 0; + + btLock(handleSem, &handleVar); + dnode = btGetNodeFromVnid(dir_vnid); + btUnlock(handleSem, &handleVar); + + if (!dnode) + return EACCES; + + // Search all nodes for one with the given parent vnid and file + // name. If one is found, we can simply use that node to fill in + // the new handle. + fnode = btFindNode(dnode, fileName); + if (fnode) + { + *file_vnid = fnode->vnid; + + folder = btGetLocalFileName(pathBuf, *file_vnid); + if (folder) + if (lstat(folder, &st) != 0) + { + btRemoveHandle(*file_vnid); + *file_vnid = 0; + return ENOENT; + } + } + else + { + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, fileName); + if (lstat(path, &st) != 0) + return ENOENT; + + *file_vnid = st.st_ino; + btAddHandle(dir_vnid, *file_vnid, fileName); + } + } + + return B_OK; +} + +int btStat(char *pathBuf, vnode_id vnid, struct stat *st) +{ + char *fileName; + int error; + + fileName = btGetLocalFileName(pathBuf, vnid); + if (fileName) + { + error = lstat(fileName, st); + return (error != 0 ? ENOENT : B_OK); + } + + return ENOENT; +} + +int btReadDir(char *pathBuf, vnode_id dir_vnid, DIR **dir, vnode_id *file_vnid, char *filename, struct stat *st) +{ + struct dirent *dirInfo; + char *folder, path[B_PATH_NAME_LENGTH]; + + if (dir_vnid == 0 || !file_vnid || !filename) + return EINVAL; + + if (!*dir) + { + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + *dir = opendir(folder); + } + + if (*dir) + { + if ((dirInfo = readdir(*dir)) != NULL) + { + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, dirInfo->d_name); + if (lstat(path, st) != 0) + return ENOENT; + + strcpy(filename, dirInfo->d_name); + *file_vnid = st->st_ino; + btAddHandle(dir_vnid, *file_vnid, filename); + return B_OK; + } + } + else + { + closedir(*dir); + return ENOENT; + } + } + + return EINVAL; +} + +int32 btRead(char *pathBuf, vnode_id vnid, off_t pos, int32 len, char *buffer) +{ + char *path; + int bytes; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + int file = open(path, O_RDONLY); + if (file < 0) + return errno; + + lseek(file, (int32) pos, SEEK_SET); + bytes = read(file, buffer, len); + close(file); + + // Return zero on any error. + if (bytes == -1) + bytes = 0; + + buffer[bytes] = 0; + return bytes; + } + + return 0; +} + +int32 btWrite(bt_session_t *session, vnode_id vnid, off_t pos, int32 len, int32 totalLen, char *buffer) +{ + bt_block *block; + + // If we've been given a total length, then we have a new buffered write + // session coming. A block will need to be allocated. + if (totalLen > 0) + { + // Make sure we don't have a wildly inaccurate total length to allocate. + if (totalLen > 10 * 1024 * 1024) + return 0; + + // Allocate a new buffered I/O block. + block = (bt_block *) malloc(sizeof(bt_block)); + if (block) + { + block->vnid = vnid; + block->pos = pos; + block->len = totalLen; + block->count = 0; + + block->buffer = (char *) malloc(totalLen + 1); + if (!block->buffer) + { + free(block); + return 0; + } + + btInsertWriteBlock(session, block); + } + else + return 0; + } + else + { + block = btGetWriteBlock(session, vnid); + if (!block) + return 0; + } + + memcpy(block->buffer + block->count, buffer, len); + block->count += len; + return len; +} + +// btGetWriteBlock() +// +bt_block *btGetWriteBlock(bt_session_t *session, vnode_id vnid) +{ + bt_block *block; + + btLock(session->blockSem, &session->blockVar); + + block = session->rootBlock; + while (block && block->vnid != vnid) + block = block->next; + + btUnlock(session->blockSem, &session->blockVar); + return block; +} + +// btInsertWriteBlock() +// +void btInsertWriteBlock(bt_session_t *session, bt_block *block) +{ + btLock(session->blockSem, &session->blockVar); + + block->next = session->rootBlock; + block->prev = NULL; + if (session->rootBlock) + session->rootBlock->prev = block; + + session->rootBlock = block; + + btUnlock(session->blockSem, &session->blockVar); +} + +int btCommit(bt_session_t *session, vnode_id vnid) +{ + bt_block *block; + char *path; + int file; + + // Get the full path for the specified file. + path = btGetLocalFileName(session->pathBuffer, vnid); + if (!path) + return ENOENT; + + // Obtain the buffered I/O block. If one can't be found, no buffered I/O + // session was started for this vnode. + block = btGetWriteBlock(session, vnid); + if (!block) + return ENOENT; + + // Open the file for writing. + file = open(path, O_WRONLY | O_CREAT); + if (file < 0) + return errno; + + btLock(session->blockSem, &session->blockVar); + + // Write the data. + lseek(file, (int32) block->pos, SEEK_SET); + write(file, block->buffer, block->len); + + btRemoveWriteBlock(session, block); + btUnlock(session->blockSem, &session->blockVar); + + close(file); + return B_OK; +} + +void btRemoveWriteBlock(bt_session_t *session, bt_block *block) +{ + // If we're removing the root, then adjust the root block pointer. + if (session->rootBlock == block) + session->rootBlock = block->next; + + // If there's a previous block, it should now point beyond this block. + if (block->prev) + block->prev->next = block->next; + + // If there's a next block, it should now point to the current predecessor. + if (block->next) + block->next->prev = block->prev; + + // Release the memory used by this block. + free(block->buffer); + free(block); +} + +int btCreate(char *pathBuf, vnode_id dir_vnid, char *name, int omode, int perms, vnode_id *file_vnid) +{ + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + int fh; + + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + fh = open(path, O_WRONLY | O_CREAT | O_TRUNC | omode, perms); + if (fh == -1) + return errno; + else + { + close(fh); + if (lstat(path, &st) == 0) + { + *file_vnid = st.st_ino; + btAddHandle(dir_vnid, *file_vnid, name); + } + else + return EACCES; + } + } + + return B_OK; +} + +int btTruncate(char *pathBuf, vnode_id vnid, int64 len) +{ + char *path; + int error; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + error = truncate(path, len); + if (error == -1) + return errno; + + return B_OK; + } + + return EACCES; +} + +// btCreateDir() +// +int btCreateDir(char *pathBuf, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, struct stat *st) +{ + char path[B_PATH_NAME_LENGTH], *folder; + + folder = btGetLocalFileName(pathBuf, dir_vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + if (mkdir(path, perms) != B_OK) + return EACCES; + + if (lstat(path, st) != 0) + return errno; + + *file_vnid = st->st_ino; + btAddHandle(dir_vnid, *file_vnid, name); + return B_OK; + } + + return ENOENT; +} + +// btDeleteDir() +// +int btDeleteDir(char *pathBuf, vnode_id vnid, char *name) +{ + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + + folder = btGetLocalFileName(pathBuf, vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + if (lstat(path, &st) != 0) + return errno; + + if (rmdir(path) == -1) + return errno; + + btPurgeNodes(st.st_ino); + return B_OK; + } + + return ENOENT; +} + +// btRename() +// +int btRename(char *pathBuf, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName) +{ + struct stat st; + char oldPath[B_PATH_NAME_LENGTH], newPath[B_PATH_NAME_LENGTH], *oldFolder, *newFolder; + + oldFolder = btGetLocalFileName(pathBuf, old_vnid); + if (oldFolder) + { + sprintf(oldPath, "%s/%s", oldFolder, oldName); + + newFolder = btGetLocalFileName(pathBuf, new_vnid); + if (newFolder) + { + sprintf(newPath, "%s/%s", newFolder, newName); + + if (lstat(oldPath, &st) != 0) + return errno; + + btPurgeNodes(st.st_ino); + + if (rename(oldPath, newPath) == -1) + return errno; + + return B_OK; + } + } + + return ENOENT; +} + +// btUnlink() +// +int btUnlink(char *pathBuf, vnode_id vnid, char *name) +{ + struct stat st; + char path[B_PATH_NAME_LENGTH], *folder; + int error; + + folder = btGetLocalFileName(pathBuf, vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + + // Obtain the inode (vnid) of the specified file through lstat(). + if (lstat(path, &st) != 0) + return errno; + + // Construct a dummy file descriptor and cause it to be removed from + // the list. + btRemoveHandle(st.st_ino); + + error = unlink(path); + return (error == -1 ? errno : B_OK); + } + + return EACCES; +} + +int btReadLink(char *pathBuf, vnode_id vnid, char *buffer, int length) +{ + char *path; + int error; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + error = readlink(path, buffer, length); + if (error == -1) + return errno; + + // If readlink() didn't return -1, it returned the number of bytes supplied in the + // buffer. It seems, however, that it does not null-terminate the string for us. + buffer[error] = 0; + return B_OK; + } + + return ENOENT; +} + +int btSymLink(char *pathBuf, vnode_id vnid, char *name, char *dest) +{ + char path[B_PATH_NAME_LENGTH], *folder; + + folder = btGetLocalFileName(pathBuf, vnid); + if (folder) + { + sprintf(path, "%s/%s", folder, name); + if (symlink(dest, path) == -1) + return errno; + + return B_OK; + } + + return ENOENT; +} + +int btWStat(char *pathBuf, vnode_id vnid, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime) +{ + struct utimbuf ftimes; + struct stat st; + char *path; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + if (mask & WSTAT_MODE) + chmod(path, mode); + + // BeOS doesn't support passing -1 as the user ID or group ID, which normally would + // simply leave the value unchanged. This complicates things a bit, but keep in + // mind that BeOS doesn't really support multiple users anyway. + if (mask & WSTAT_UID && mask & WSTAT_GID) + chown(path, uid, gid); + +// if (mask & WSTAT_UID) +// chown(path, uid, -1); + +// if (mask & WSTAT_GID) +// chown(path, -1, gid); + + if (mask & WSTAT_SIZE) + truncate(path, size); + + if (lstat(path, &st) == 0) + if (mask & WSTAT_ATIME || mask & WSTAT_MTIME) + { + ftimes.actime = mask & WSTAT_ATIME ? atime : st.st_atime; + ftimes.modtime = mask & WSTAT_MTIME ? mtime : st.st_mtime; + utime(path, &ftimes); + } + + return B_OK; + } + + return ENOENT; +} + +int btReadAttrib(char *pathBuf, vnode_id vnid, char *name, int32 dataType, void *buffer, int32 pos, int32 len) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int bytes = (int) fs_read_attr(file, name, dataType, pos, buffer, len); + close(file); + + if ((dataType == B_STRING_TYPE || dataType == B_MIME_TYPE) && bytes < len && bytes >= 0) + ((char *) buffer)[bytes] = 0; + + return bytes; + } + } + + return ENOENT; +} + +int btWriteAttrib(char *pathBuf, vnode_id vnid, char *name, int32 dataType, void *buffer, int32 pos, int32 len) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int bytes = (int) fs_write_attr(file, name, dataType, pos, buffer, len); + close(file); + return bytes; + } + } + + return ENOENT; +} + +int btReadAttribDir(char *pathBuf, vnode_id vnid, DIR **dir, char *attrName) +{ + dirent_t *entry; + char *path; + + if (!attrName) + return EINVAL; + + if (!*dir) + { + path = btGetLocalFileName(pathBuf, vnid); + if (path) + *dir = fs_open_attr_dir(path); + } + + if (*dir) + do + { + entry = fs_read_attr_dir(*dir); + if (entry) + { + if (strncmp(entry->d_name, "_trk/", 5) == 0) + continue; + + strcpy(attrName, entry->d_name); + return B_OK; + } + } while (entry); + + if (*dir) + fs_close_attr_dir(*dir); + + return ENOENT; +} + +int btRemoveAttrib(char *pathBuf, vnode_id vnid, char *name) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int error = fs_remove_attr(file, name); + if (error == -1) + error = errno; + + close(file); + return error; + } + } + + return ENOENT; +} + +int btStatAttrib(char *pathBuf, vnode_id vnid, char *name, struct attr_info *info) +{ + char *path; + int file; + + path = btGetLocalFileName(pathBuf, vnid); + if (path) + { + file = open(path, O_RDONLY); + + if (file) + { + int error = fs_stat_attr(file, name, info); + if (error == -1) + error = errno; + + close(file); + return error; + } + } + + return ENOENT; +} + +int btReadIndexDir(char *rootPath, DIR **dir, char *indexName) +{ + struct dirent *dirInfo; + + if (!*dir) + { + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + *dir = fs_open_index_dir(device); + } + + if (*dir) + if ((dirInfo = fs_read_index_dir(*dir)) != NULL) + { + strcpy(indexName, dirInfo->d_name); + return B_OK; + } + else + { + fs_close_index_dir(*dir); + *dir = NULL; + return ENOENT; + } + + return ENOENT; +} + +int btCreateIndex(char *rootPath, char *name, int type, int flags) +{ + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + if (fs_create_index(device, name, type, flags) == -1) + return errno; + + return B_OK; +} + +int btRemoveIndex(char *rootPath, char *name) +{ + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + if (fs_remove_index(device, name) == -1) + return errno; + + return B_OK; +} + +int btStatIndex(char *rootPath, char *name, struct index_info *info) +{ + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + if (fs_stat_index(device, name, info) == -1) + return errno; + + return B_OK; +} + +int btReadQuery(char *rootPath, DIR **dir, char *query, char *fileName, vnode_id *vnid, vnode_id *parent) +{ + struct dirent *dirInfo; + + if (!*dir) + { + dev_t device = dev_for_path(rootPath); + if (device < 0) + return device; + + *dir = fs_open_query(device, query, 0); + } + + if (*dir) + if ((dirInfo = fs_read_query(*dir)) != NULL) + { + *vnid = dirInfo->d_ino; + *parent = dirInfo->d_pino; + strcpy(fileName, dirInfo->d_name); + return B_OK; + } + else + { + fs_close_query(*dir); + *dir = NULL; + return ENOENT; + } + + return ENOENT; +} + +//////////////////////////////////////////////////////////////////// + +void netbtPreMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, security; + + client = session->socket; + if (argc == 1) + { + if (argv[0].type == B_STRING_TYPE) + { + security = btPreMount(session, argv[0].data); + btRPCCreateAck(&packet, xid, security); + btRPCSendAck(client, &packet); + return; + } + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + vnode_id vnid; + int client, error; + + client = session->socket; + if (argc == 3) + { + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE && + argv[2].type == B_STRING_TYPE) + { + char *shareName = argv[0].data; + char *user = argv[1].data; + char *password = argv[2].data; + error = btMount(session, shareName, user, password, &vnid); + if (error == B_OK) + { + // Record this session having logged in to a specific share. + session->share = btGetShareId(shareName); + session->logon = time(NULL); + + // Now send the client a response with the root vnid. + btRPCCreateAck(&packet, xid, error); + btRPCPutInt64(&packet, vnid); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); + return; + } + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + { + if (argv[0].type == B_INT64_TYPE) + { + fs_info info; + + error = btGetFSInfo(fileShares[session->share].path, &info); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCPutInt32(&packet, info.block_size); + btRPCPutInt32(&packet, info.total_blocks); + btRPCPutInt32(&packet, info.free_blocks); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); + return; + } + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + struct stat st; + int client, error; + + client = session->socket; + if (argc == 2) + { + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE) + { + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + error = btLookup(session->pathBuffer, dir_vnid, argv[1].data, &file_vnid); + if (error == B_OK) + error = btStat(session->pathBuffer, file_vnid, &st); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt64(&packet, file_vnid); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); + return; + } + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + struct stat st; + int client, error; + + client = session->socket; + if (argc == 2) + { + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE) + { + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + DIR *dir; + char filename[B_PATH_NAME_LENGTH]; + int entries = 0; + + dir = (DIR *)(*((int32 *) argv[1].data)); + error = btReadDir(session->pathBuffer, dir_vnid, &dir, &file_vnid, filename, &st); + + if (error != B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + btRPCCreateAck(&packet, xid, B_OK); + while (error == B_OK) + { + btRPCPutInt64(&packet, file_vnid); + btRPCPutString(&packet, filename, strlen(filename)); + btRPCPutInt32(&packet, (int32) dir); + btRPCPutStat(&packet, &st); + + if (++entries >= 32) + break; + + error = btReadDir(session->pathBuffer, dir_vnid, &dir, &file_vnid, filename, &st); + btRPCPutInt32(&packet, error); + } + + // If we exhausted the list of directory entries without filling + // the buffer, add an error message that will prevent the client + // from requesting further entries. + if (entries < 32) + btRPCPutInt32(&packet, ENOENT); + + btRPCSendAck(client, &packet); + return; + } + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + if (argv[0].type == B_INT64_TYPE) + { + struct stat info; + vnode_id vnid = *((vnode_id *) argv[0].data); + + error = btStat(session->pathBuffer, vnid, &info); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCPutStat(&packet, &info); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + if (argc == 3) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_INT32_TYPE && argv[2].type == B_INT32_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + off_t pos = *((off_t *) argv[1].data); + int32 len = *((int32 *) argv[2].data); + int32 bytes = 0; + + session->ioBuffer[len] = 0; + bytes = btRead(session->pathBuffer, vnid, pos, len, session->ioBuffer); + + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutString(&packet, session->ioBuffer, bytes); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + int client; + + client = session->socket; + if (argc == 5) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_INT64_TYPE && + argv[2].type == B_INT32_TYPE && argv[3].type == B_INT32_TYPE && + argv[4].type == B_STRING_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + off_t pos = *((off_t *) argv[1].data); + int32 len = *((int32 *) argv[2].data); + int32 totalLen = *((int32 *) argv[3].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (session->rights & BT_RIGHTS_WRITE) + btWrite(session, vnid, pos, len, totalLen, argv[4].data); + } +} + +void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + struct stat st; + int client, error; + + client = session->socket; + if (argc == 4) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_INT32_TYPE && argv[3].type == B_INT32_TYPE) + { + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + int omode = *((int *) argv[2].data); + int perms = *((int *) argv[3].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btCreate(session->pathBuffer, dir_vnid, argv[1].data, omode, perms, &file_vnid); + if (error == B_OK) + error = btStat(session->pathBuffer, file_vnid, &st); + + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt64(&packet, file_vnid); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_INT64_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btTruncate(session->pathBuffer, vnid, *((int64 *) argv[1].data)); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btUnlink(session->pathBuffer, vnid, argv[1].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 4) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_INT64_TYPE && argv[3].type == B_STRING_TYPE) + { + vnode_id old_vnid = *((vnode_id *) argv[0].data); + vnode_id new_vnid = *((vnode_id *) argv[2].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btRename(session->pathBuffer, old_vnid, argv[1].data, new_vnid, argv[3].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 3) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_INT32_TYPE) + { + vnode_id dir_vnid = *((vnode_id *) argv[0].data); + vnode_id file_vnid; + struct stat st; + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btCreateDir(session->pathBuffer, dir_vnid, argv[1].data, *((int *) argv[2].data), &file_vnid, &st); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt64(&packet, file_vnid); + btRPCPutStat(&packet, &st); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btDeleteDir(session->pathBuffer, vnid, argv[1].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + if (argv[0].type == B_INT64_TYPE) + { + char path[B_PATH_NAME_LENGTH]; + vnode_id vnid = *((vnode_id *) argv[0].data); + + error = btReadLink(session->pathBuffer, vnid, path, B_PATH_NAME_LENGTH); + if (error == B_OK) + { + int length = strlen(path); + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutString(&packet, path, length); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 3) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_STRING_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btSymLink(session->pathBuffer, vnid, argv[1].data, argv[2].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 8) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_INT32_TYPE && argv[2].type == B_INT32_TYPE && + argv[3].type == B_INT32_TYPE && argv[4].type == B_INT32_TYPE && argv[5].type == B_INT32_TYPE && + argv[6].type == B_INT32_TYPE && argv[7].type == B_INT32_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + int32 mask = *((int32 *) argv[1].data); + int32 mode = *((int32 *) argv[2].data); + int32 uid = *((int32 *) argv[3].data); + int32 gid = *((int32 *) argv[4].data); + int64 size = (int64) *((int32 *) argv[5].data); + int32 atime = *((int32 *) argv[6].data); + int32 mtime = *((int32 *) argv[7].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btWStat(session->pathBuffer, vnid, mask, mode, uid, gid, size, atime, mtime); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, bytesRead; + + client = session->socket; + if (argc == 5) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_INT32_TYPE && + argv[3].type == B_INT32_TYPE && argv[4].type == B_INT32_TYPE) + { + char *buffer; + vnode_id vnid = *((vnode_id *) argv[0].data); + int32 type = *((int32 *) argv[2].data); + int32 pos = *((int32 *) argv[3].data); + int32 len = *((int32 *) argv[4].data); + + if (len <= BT_MAX_ATTR_BUFFER) + buffer = session->attrBuffer; + else + buffer = (char *) malloc(len + 1); + + if (buffer) + { + bytesRead = btReadAttrib(session->pathBuffer, vnid, argv[1].data, type, buffer, pos, len); + if (bytesRead >= 0) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt32(&packet, (int32) bytesRead); + if (bytesRead > 0) + btRPCPutString(&packet, buffer, bytesRead); + } + else + btRPCCreateAck(&packet, xid, B_ENTRY_NOT_FOUND); + + if (len > BT_MAX_ATTR_BUFFER) + free(buffer); + } + else + btRPCCreateAck(&packet, xid, ENOMEM); + + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, bytesWritten; + + client = session->socket; + if (argc == 6) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE && argv[2].type == B_INT32_TYPE && + argv[3].type == B_STRING_TYPE && argv[4].type == B_INT32_TYPE && argv[5].type == B_INT32_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + int32 type = *((int32 *) argv[2].data); + int32 pos = *((int32 *) argv[4].data); + int32 len = *((int32 *) argv[5].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + bytesWritten = btWriteAttrib(session->pathBuffer, vnid, argv[1].data, type, argv[3].data, pos, len); + if (bytesWritten >= 0) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt32(&packet, (int32) bytesWritten); + } + else + btRPCCreateAck(&packet, xid, B_ENTRY_NOT_FOUND); + + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + { + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + DIR *dir = (DIR *)(*((int32 *) argv[1].data)); + char attrName[100]; + int entries = 0; + + error = btReadAttribDir(session->pathBuffer, vnid, &dir, attrName); + + if (error != B_OK) + { + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + btRPCCreateAck(&packet, xid, B_OK); + while (error == B_OK) + { + btRPCPutString(&packet, attrName, strlen(attrName)); + btRPCPutInt32(&packet, (int32) dir); + + if (++entries >= 32) + break; + + error = btReadAttribDir(session->pathBuffer, vnid, &dir, attrName); + btRPCPutInt32(&packet, error); + } + + if (entries < 32) + btRPCPutInt32(&packet, ENOENT); + + btRPCSendAck(client, &packet); + return; + } + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btRemoveAttrib(session->pathBuffer, vnid, argv[1].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_INT64_TYPE && argv[1].type == B_STRING_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + struct attr_info info; + + error = btStatAttrib(session->pathBuffer, vnid, argv[1].data, &info); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt32(&packet, info.type); + btRPCPutInt64(&packet, info.size); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + if (argv[0].type == B_STRING_TYPE) + { + DIR *dir; + char indexName[100]; + + dir = (DIR *)(*((int32 *) argv[0].data)); + + error = btReadIndexDir(fileShares[session->share].path, &dir, indexName); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutString(&packet, indexName, strlen(indexName)); + btRPCPutInt32(&packet, (int32) dir); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 3) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_INT32_TYPE && argv[2].type == B_INT32_TYPE) + { + int type = *((int32 *) argv[1].data); + int flags = *((int32 *) argv[2].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btCreateIndex(fileShares[session->share].path, argv[0].data, type, flags); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + if (argv[0].type == B_STRING_TYPE) + { + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btRemoveIndex(fileShares[session->share].path, argv[0].data); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + if (argv[0].type == B_STRING_TYPE) + { + struct index_info info; + + error = btStatIndex(fileShares[session->share].path, argv[0].data, &info); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt32(&packet, info.type); + btRPCPutInt64(&packet, info.size); + btRPCPutInt32(&packet, info.modification_time); + btRPCPutInt32(&packet, info.creation_time); + btRPCPutInt32(&packet, info.uid); + btRPCPutInt32(&packet, info.gid); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 2) + if (argv[0].type == B_STRING_TYPE && argv[1].type == B_STRING_TYPE) + { + DIR *dir; + char fileName[B_PATH_NAME_LENGTH]; + vnode_id vnid, parent; + + dir = (DIR *)(*((int32 *) argv[0].data)); + + error = btReadQuery(fileShares[session->share].path, &dir, argv[1].data, fileName, &vnid, &parent); + if (error == B_OK) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCPutInt64(&packet, vnid); + btRPCPutInt64(&packet, parent); + btRPCPutString(&packet, fileName, strlen(fileName)); + btRPCPutInt32(&packet, (int32) dir); + } + else + btRPCCreateAck(&packet, xid, error); + + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +// netbtCommit() +// +void netbtCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client, error; + + client = session->socket; + if (argc == 1) + if (argv[0].type == B_INT64_TYPE) + { + vnode_id vnid = *((vnode_id *) argv[0].data); + + // If the file share this user is connected to is read-only, the command + // cannot be honored. + if (!(session->rights & BT_RIGHTS_WRITE)) + { + btRPCCreateAck(&packet, xid, EACCES); + btRPCSendAck(client, &packet); + return; + } + + error = btCommit(session, vnid); + btRPCCreateAck(&packet, xid, error); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} + +void netbtPrintJobNew(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, EOPNOTSUPP); + btRPCSendAck(client, &packet); +} + +void netbtPrintJobData(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, EOPNOTSUPP); + btRPCSendAck(client, &packet); +} + +void netbtPrintJobCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, EOPNOTSUPP); + btRPCSendAck(client, &packet); +} + +void netbtAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + btRPCCreateAck(&packet, xid, EOPNOTSUPP); + btRPCSendAck(client, &packet); +} + +// netbtQuit() +// +void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) +{ + bt_outPacket packet; + int client; + + client = session->socket; + if (argc == 0) + { + btRPCCreateAck(&packet, xid, B_OK); + btRPCSendAck(client, &packet); + return; + } + + sendErrorToClient(client, xid, EINVAL); +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/server/betalk.h new file mode 100644 index 0000000000..fb9f3dad3f --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +// The different types of network resources supported by BeServed. +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRITNER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 8192 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 128 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int nsid; + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +typedef struct rpcInfo +{ + thread_id rpcThread; + int32 quitXID; + + uint32 serverIP; + int32 serverPort; + int s; +} bt_rpcinfo; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket inPacket; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server/fsproto.h b/src/tests/add-ons/kernel/file_systems/beserved/server/fsproto.h new file mode 100644 index 0000000000..a6072837d5 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server/fsproto.h @@ -0,0 +1,246 @@ +#ifndef _FSPROTO_H +#define _FSPROTO_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef dev_t nspace_id; +typedef ino_t vnode_id; + +/* UGLY UGLY UGLY */ +#ifndef _DRIVERS_H +struct selectsync; +typedef struct selectsync selectsync; +#endif + + +/* + * PUBLIC PART OF THE FILE SYSTEM PROTOCOL + */ + +#define WSTAT_MODE 0x0001 +#define WSTAT_UID 0x0002 +#define WSTAT_GID 0x0004 +#define WSTAT_SIZE 0x0008 +#define WSTAT_ATIME 0x0010 +#define WSTAT_MTIME 0x0020 +#define WSTAT_CRTIME 0x0040 + +#define WFSSTAT_NAME 0x0001 + +#define B_ENTRY_CREATED 1 +#define B_ENTRY_REMOVED 2 +#define B_ENTRY_MOVED 3 +#define B_STAT_CHANGED 4 +#define B_ATTR_CHANGED 5 +#define B_DEVICE_MOUNTED 6 +#define B_DEVICE_UNMOUNTED 7 + +#define B_STOP_WATCHING 0x0000 +#define B_WATCH_NAME 0x0001 +#define B_WATCH_STAT 0x0002 +#define B_WATCH_ATTR 0x0004 +#define B_WATCH_DIRECTORY 0x0008 + +#define SELECT_READ 1 +#define SELECT_WRITE 2 +#define SELECT_EXCEPTION 3 + +#define B_CUR_FS_API_VERSION 2 + +struct attr_info; +struct index_info; + +typedef int op_read_vnode(void *ns, vnode_id vnid, char r, void **node); +typedef int op_write_vnode(void *ns, void *node, char r); +typedef int op_remove_vnode(void *ns, void *node, char r); +typedef int op_secure_vnode(void *ns, void *node); + +typedef int op_walk(void *ns, void *base, const char *file, char **newpath, + vnode_id *vnid); + +typedef int op_access(void *ns, void *node, int mode); + +typedef int op_create(void *ns, void *dir, const char *name, + int omode, int perms, vnode_id *vnid, void **cookie); +typedef int op_mkdir(void *ns, void *dir, const char *name, int perms); +typedef int op_symlink(void *ns, void *dir, const char *name, + const char *path); +typedef int op_link(void *ns, void *dir, const char *name, void *node); + +typedef int op_rename(void *ns, void *olddir, const char *oldname, + void *newdir, const char *newname); +typedef int op_unlink(void *ns, void *dir, const char *name); +typedef int op_rmdir(void *ns, void *dir, const char *name); + +typedef int op_readlink(void *ns, void *node, char *buf, size_t *bufsize); + +typedef int op_opendir(void *ns, void *node, void **cookie); +typedef int op_closedir(void *ns, void *node, void *cookie); +typedef int op_rewinddir(void *ns, void *node, void *cookie); +typedef int op_readdir(void *ns, void *node, void *cookie, long *num, + struct dirent *buf, size_t bufsize); + +typedef int op_open(void *ns, void *node, int omode, void **cookie); +typedef int op_close(void *ns, void *node, void *cookie); +typedef int op_free_cookie(void *ns, void *node, void *cookie); +typedef int op_read(void *ns, void *node, void *cookie, off_t pos, void *buf, + size_t *len); +typedef int op_write(void *ns, void *node, void *cookie, off_t pos, + const void *buf, size_t *len); +typedef int op_readv(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, + size_t count, size_t *len); +typedef int op_writev(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, + size_t count, size_t *len); +typedef int op_ioctl(void *ns, void *node, void *cookie, int cmd, void *buf, + size_t len); +typedef int op_setflags(void *ns, void *node, void *cookie, int flags); + +typedef int op_rstat(void *ns, void *node, struct stat *); +typedef int op_wstat(void *ns, void *node, struct stat *, long mask); +typedef int op_fsync(void *ns, void *node); + +typedef int op_select(void *ns, void *node, void *cookie, uint8 event, + uint32 ref, selectsync *sync); +typedef int op_deselect(void *ns, void *node, void *cookie, uint8 event, + selectsync *sync); + +typedef int op_initialize(const char *devname, void *parms, size_t len); +typedef int op_mount(nspace_id nsid, const char *devname, ulong flags, + void *parms, size_t len, void **data, vnode_id *vnid); +typedef int op_unmount(void *ns); +typedef int op_sync(void *ns); +typedef int op_rfsstat(void *ns, struct fs_info *); +typedef int op_wfsstat(void *ns, struct fs_info *, long mask); + + +typedef int op_open_attrdir(void *ns, void *node, void **cookie); +typedef int op_close_attrdir(void *ns, void *node, void *cookie); +typedef int op_rewind_attrdir(void *ns, void *node, void *cookie); +typedef int op_read_attrdir(void *ns, void *node, void *cookie, long *num, + struct dirent *buf, size_t bufsize); +typedef int op_remove_attr(void *ns, void *node, const char *name); +typedef int op_rename_attr(void *ns, void *node, const char *oldname, + const char *newname); +typedef int op_stat_attr(void *ns, void *node, const char *name, + struct attr_info *buf); + +typedef int op_write_attr(void *ns, void *node, const char *name, int type, + const void *buf, size_t *len, off_t pos); +typedef int op_read_attr(void *ns, void *node, const char *name, int type, + void *buf, size_t *len, off_t pos); + +typedef int op_open_indexdir(void *ns, void **cookie); +typedef int op_close_indexdir(void *ns, void *cookie); +typedef int op_rewind_indexdir(void *ns, void *cookie); +typedef int op_read_indexdir(void *ns, void *cookie, long *num, + struct dirent *buf, size_t bufsize); +typedef int op_create_index(void *ns, const char *name, int type, int flags); +typedef int op_remove_index(void *ns, const char *name); +typedef int op_rename_index(void *ns, const char *oldname, + const char *newname); +typedef int op_stat_index(void *ns, const char *name, struct index_info *buf); + +typedef int op_open_query(void *ns, const char *query, ulong flags, + port_id port, long token, void **cookie); +typedef int op_close_query(void *ns, void *cookie); +typedef int op_read_query(void *ns, void *cookie, long *num, + struct dirent *buf, size_t bufsize); + +typedef struct vnode_ops { + op_read_vnode (*read_vnode); + op_write_vnode (*write_vnode); + op_remove_vnode (*remove_vnode); + op_secure_vnode (*secure_vnode); + op_walk (*walk); + op_access (*access); + op_create (*create); + op_mkdir (*mkdir); + op_symlink (*symlink); + op_link (*link); + op_rename (*rename); + op_unlink (*unlink); + op_rmdir (*rmdir); + op_readlink (*readlink); + op_opendir (*opendir); + op_closedir (*closedir); + op_free_cookie (*free_dircookie); + op_rewinddir (*rewinddir); + op_readdir (*readdir); + op_open (*open); + op_close (*close); + op_free_cookie (*free_cookie); + op_read (*read); + op_write (*write); + op_readv (*readv); + op_writev (*writev); + op_ioctl (*ioctl); + op_setflags (*setflags); + op_rstat (*rstat); + op_wstat (*wstat); + op_fsync (*fsync); + op_initialize (*initialize); + op_mount (*mount); + op_unmount (*unmount); + op_sync (*sync); + op_rfsstat (*rfsstat); + op_wfsstat (*wfsstat); + op_select (*select); + op_deselect (*deselect); + op_open_indexdir (*open_indexdir); + op_close_indexdir (*close_indexdir); + op_free_cookie (*free_indexdircookie); + op_rewind_indexdir (*rewind_indexdir); + op_read_indexdir (*read_indexdir); + op_create_index (*create_index); + op_remove_index (*remove_index); + op_rename_index (*rename_index); + op_stat_index (*stat_index); + op_open_attrdir (*open_attrdir); + op_close_attrdir (*close_attrdir); + op_free_cookie (*free_attrdircookie); + op_rewind_attrdir (*rewind_attrdir); + op_read_attrdir (*read_attrdir); + op_write_attr (*write_attr); + op_read_attr (*read_attr); + op_remove_attr (*remove_attr); + op_rename_attr (*rename_attr); + op_stat_attr (*stat_attr); + op_open_query (*open_query); + op_close_query (*close_query); + op_free_cookie (*free_querycookie); + op_read_query (*read_query); +} vnode_ops; + +extern _IMPEXP_KERNEL int new_path(const char *path, char **copy); +extern _IMPEXP_KERNEL void free_path(char *p); + +extern _IMPEXP_KERNEL int notify_listener(int op, nspace_id nsid, + vnode_id vnida, vnode_id vnidb, + vnode_id vnidc, const char *name); +extern _IMPEXP_KERNEL void notify_select_event(selectsync *sync, uint32 ref); +extern _IMPEXP_KERNEL int send_notification(port_id port, long token, + ulong what, long op, nspace_id nsida, + nspace_id nsidb, vnode_id vnida, + vnode_id vnidb, vnode_id vnidc, + const char *name); +extern _IMPEXP_KERNEL int get_vnode(nspace_id nsid, vnode_id vnid, void **data); +extern _IMPEXP_KERNEL int put_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int new_vnode(nspace_id nsid, vnode_id vnid, void *data); +extern _IMPEXP_KERNEL int remove_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int unremove_vnode(nspace_id nsid, vnode_id vnid); +extern _IMPEXP_KERNEL int is_vnode_removed(nspace_id nsid, vnode_id vnid); + + +extern _EXPORT vnode_ops fs_entry; +extern _EXPORT int32 api_version; + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/server/sysdepdefs.h b/src/tests/add-ons/kernel/file_systems/beserved/server/sysdepdefs.h new file mode 100644 index 0000000000..6bb4bd5051 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/server/sysdepdefs.h @@ -0,0 +1,10 @@ +#ifndef _SYSDEPDEFS_H_ +#define _SYSDEPDEFS_H_ + +#ifdef BONE_VERSION + +#define closesocket(s) close(s) + +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/BlowFish.cpp b/src/tests/add-ons/kernel/file_systems/beserved/transport/BlowFish.cpp new file mode 100644 index 0000000000..789eab32a9 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/BlowFish.cpp @@ -0,0 +1,189 @@ +/* blowfish.c */ + +#include "BlowFish.h" +#include "BlowFishTable.h" + +#define N 16 +#define noErr 0 +#define DATAERROR -1 +#define KEYBYTES 8 + +unsigned long F(blf_ctx *bc, unsigned long x) +{ + unsigned long a; + unsigned long b; + unsigned long c; + unsigned long d; + unsigned long y; + + d = x & 0x00FF; + x >>= 8; + c = x & 0x00FF; + x >>= 8; + b = x & 0x00FF; + x >>= 8; + a = x & 0x00FF; + y = bc->S[0][a] + bc->S[1][b]; + y = y ^ bc->S[2][c]; + y = y + bc->S[3][d]; + + return y; +} + +void Blowfish_encipher(blf_ctx *bc, unsigned long *xl, unsigned long *xr) +{ + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = 0; i < N; ++i) + { + Xl = Xl ^ bc->P[i]; + Xr = F(bc, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ bc->P[N]; + Xl = Xl ^ bc->P[N + 1]; + + *xl = Xl; + *xr = Xr; +} + +void Blowfish_decipher(blf_ctx *bc, unsigned long *xl, unsigned long *xr) +{ + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = N + 1; i > 1; --i) + { + Xl = Xl ^ bc->P[i]; + Xr = F(bc, Xl) ^ Xr; + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + } + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ bc->P[1]; + Xl = Xl ^ bc->P[0]; + + *xl = Xl; + *xr = Xr; +} + +short InitializeBlowfish(blf_ctx *bc, unsigned char key[], int keybytes) +{ + short i; + short j; + short k; + unsigned long data; + unsigned long datal; + unsigned long datar; + + /* initialise p & s-boxes without file read */ + for (i = 0; i < N+2; i++) + { + bc->P[i] = bfp[i]; + } + for (i = 0; i < 256; i++) + { + bc->S[0][i] = ks0[i]; + bc->S[1][i] = ks1[i]; + bc->S[2][i] = ks2[i]; + bc->S[3][i] = ks3[i]; + } + + j = 0; + for (i = 0; i < N + 2; ++i) + { + data = 0x00000000; + for (k = 0; k < 4; ++k) + { + data = (data << 8) | key[j]; + j = j + 1; + if (j >= keybytes) + { + j = 0; + } + } + bc->P[i] = bc->P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for (i = 0; i < N + 2; i += 2) + { + Blowfish_encipher(bc, &datal, &datar); + + bc->P[i] = datal; + bc->P[i + 1] = datar; + } + + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 256; j += 2) + { + + Blowfish_encipher(bc, &datal, &datar); + + bc->S[i][j] = datal; + bc->S[i][j + 1] = datar; + } + } + return 0; +} + +void blf_key (blf_ctx *c, unsigned char *k, int len) +{ + InitializeBlowfish(c, k, len); +} + +void blf_enc(blf_ctx *c, unsigned long *data, int blocks) +{ + unsigned long *d; + int i; + + d = data; + for (i = 0; i < blocks; i++) + { + Blowfish_encipher(c, d, d+1); + d += 2; + } +} + +void blf_dec(blf_ctx *c, unsigned long *data, int blocks) +{ + unsigned long *d; + int i; + + d = data; + for (i = 0; i < blocks; i++) + { + Blowfish_decipher(c, d, d+1); + d += 2; + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/BlowFish.h b/src/tests/add-ons/kernel/file_systems/beserved/transport/BlowFish.h new file mode 100644 index 0000000000..cb2d4ec01b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/BlowFish.h @@ -0,0 +1,35 @@ +/* blowfish.h */ + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +#define UWORD32 unsigned long +#define UBYTE08 unsigned char + +#define MAXKEYBYTES 56 /* 448 bits */ + +typedef struct +{ + unsigned long S[4][256], P[18]; +} blf_ctx; + +unsigned long F(blf_ctx *, unsigned long x); +void Blowfish_encipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +void Blowfish_decipher(blf_ctx *, unsigned long *xl, unsigned long *xr); +short InitializeBlowfish(blf_ctx *, unsigned char key[], int keybytes); + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE void blf_enc(blf_ctx *c, unsigned long *data, int blocks); +_IMPEXP_BESURE void blf_dec(blf_ctx *c, unsigned long *data, int blocks); +_IMPEXP_BESURE void blf_key(blf_ctx *c, unsigned char *key, int len); + +#ifdef __cplusplus +} +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/BlowFishTable.h b/src/tests/add-ons/kernel/file_systems/beserved/transport/BlowFishTable.h new file mode 100644 index 0000000000..3547ee1d19 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/BlowFishTable.h @@ -0,0 +1,280 @@ +/* bf_tab.h: Blowfish P-box and S-box tables */ + + +static UWORD32 bfp[] = +{ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b, +}; + +static UWORD32 ks0[] = +{ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + }; + static UWORD32 ks1[]= + { + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 +}; +static UWORD32 ks2[] = +{ + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 +}; +static UWORD32 ks3[] = +{ + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 +}; diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/LoginPanel.cpp b/src/tests/add-ons/kernel/file_systems/beserved/transport/LoginPanel.cpp new file mode 100644 index 0000000000..08651bafdd --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/LoginPanel.cpp @@ -0,0 +1,174 @@ +#include "Mime.h" +#include "TypeConstants.h" +#include "Application.h" +#include "InterfaceDefs.h" +#include "TranslationUtils.h" +#include "Button.h" +#include "Errors.h" +#include "Window.h" +#include "TextControl.h" +#include "Roster.h" +#include "Bitmap.h" +#include "Screen.h" +#include "OS.h" + +// POSIX includes +#include "errno.h" +#include "malloc.h" + +#include "LoginPanel.h" +#include "md5.h" + +// To create: +// BRect frame2(100, 150, 350, 290); +// LoginPanel *login = new LoginPanel(frame2); + + +// ----- LoginView ----------------------------------------------------- + +LoginView::LoginView(BRect rect, char *server, char *share) : + BView(rect, "LoginView", B_FOLLOW_ALL, B_WILL_DRAW) +{ + strcpy(resource, share); + strcat(resource, " on "); + strcat(resource, server); + + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(gray); + + BRect bmpRect(0.0, 0.0, 31.0, 31.0); + icon = new BBitmap(bmpRect, B_CMAP8); + BMimeType mime("application/x-vnd.Teldar-FileSharing"); + mime.GetIcon(icon, B_LARGE_ICON); + + BRect r(10, 72, 240, 92); + user = new BTextControl(r, "User", "User:", "", NULL); + user->SetDivider(55); + AddChild(user); + + r.top = 97; + r.bottom = r.top + 20; + password = new BTextControl(r, "Password", "Password:", "", NULL); + password->SetDivider(55); + password->TextView()->HideTyping(true); + AddChild(password); + + r.Set(LOGIN_PANEL_WIDTH - 160, LOGIN_PANEL_HEIGHT - 33, LOGIN_PANEL_WIDTH - 90, LOGIN_PANEL_HEIGHT - 13); + BButton *okBtn = new BButton(r, "OkayBtn", "Login", new BMessage(MSG_LOGIN_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + okBtn->MakeDefault(true); + AddChild(okBtn); + + r.Set(LOGIN_PANEL_WIDTH - 80, LOGIN_PANEL_HEIGHT - 33, LOGIN_PANEL_WIDTH - 10, LOGIN_PANEL_HEIGHT - 13); + AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_LOGIN_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)); +} + +LoginView::~LoginView() +{ +} + +void LoginView::Draw(BRect rect) +{ + BRect r = Bounds(); + BRect iconRect(13.0, 5.0, 45.0, 37.0); + rgb_color black = { 0, 0, 0, 255 }; + rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(gray); + SetLowColor(gray); + FillRect(r, B_SOLID_LOW); + + SetHighColor(black); + SetFont(be_bold_font); + SetFontSize(11); + MovePenTo(55, 15); + DrawString("Login Required"); + + SetFont(be_plain_font); + SetFontSize(10); + MovePenTo(55, 28); + DrawString("The print server has rejected your user name and"); + MovePenTo(55, 40); + DrawString("password. Please re-enter your user credentials."); + + MovePenTo(13, 61); + DrawString("Printer:"); + MovePenTo(70, 61); + DrawString(resource); + + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 0, 180); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); + DrawBitmap(icon, iconRect); +} + + +// ----- LoginPanel ---------------------------------------------------------------------- + +LoginPanel::LoginPanel(BRect frame, char *server, char *share, bool show) : + BWindow(frame, "Login", B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) +{ + user[0] = password[0] = 0; + cancelled = false; + + BRect r = Bounds(); + loginView = new LoginView(r, server, share); + AddChild(loginView); + + if (show) + Show(); +} + +LoginPanel::~LoginPanel() +{ +} + +// Center() +// +void LoginPanel::Center() +{ + BScreen screen(this); + BRect screenFrame = screen.Frame(); + BRect winFrame; + winFrame.left = (screenFrame.Width() - 300) / 2; + winFrame.top = (screenFrame.Height() - 158) / 2; + winFrame.right = winFrame.left + 300; + winFrame.bottom = winFrame.top + 158; + MoveTo(winFrame.left, winFrame.top); + ResizeTo(300, 158); + + Show(); +} + +// MessageReceived() +// +void LoginPanel::MessageReceived(BMessage *msg) +{ + switch (msg->what) + { + case MSG_LOGIN_OK: + safeStringCopy(user, loginView->GetUser(), sizeof(user)); + safeStringCopy(password, loginView->GetPassword(), sizeof(password)); + md5EncodeString(password, md5passwd); + BWindow::Quit(); + break; + + case MSG_LOGIN_CANCEL: + cancelled = true; + BWindow::Quit(); + break; + + default: + BWindow::MessageReceived(msg); + break; + } +} + +void safeStringCopy(char *dest, const char *source, int destSize) +{ + int length = strlen(source); + if (length >= destSize) + length = destSize - 1; + + strncpy(dest, source, length); + dest[length] = 0; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/LoginPanel.h b/src/tests/add-ons/kernel/file_systems/beserved/transport/LoginPanel.h new file mode 100644 index 0000000000..7b244fe654 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/LoginPanel.h @@ -0,0 +1,63 @@ +#include "Window.h" +#include "View.h" +#include "TextControl.h" +#include "Button.h" +#include "Bitmap.h" + +#include "betalk.h" + +const uint32 MSG_LOGIN_OK = 'LgOK'; +const uint32 MSG_LOGIN_CANCEL = 'LgCn'; + +#define LOGIN_PANEL_WIDTH 300 +#define LOGIN_PANEL_HEIGHT 158 + + +// ----- LoginView ----------------------------------------------------- + +class LoginView : public BView +{ + public: + LoginView(BRect rect, char *server, char *share); + ~LoginView(); + + void Draw(BRect rect); + + const char *GetUser() { return user->Text(); } + const char *GetPassword() { return password->Text(); } + + private: + BBitmap *icon; + BTextControl *user; + BTextControl *password; + char resource[256]; +}; + + +// ----- LoginPanel ---------------------------------------------------------------------- + +class LoginPanel : public BWindow +{ + public: + LoginPanel(BRect frame, char *server, char *share, bool show); + ~LoginPanel(); + + void Center(); + void MessageReceived(BMessage *msg); + bool IsCancelled() { return cancelled; } + + char user[MAX_NAME_LENGTH]; + char password[MAX_NAME_LENGTH]; + char md5passwd[MAX_NAME_LENGTH]; + + sem_id loginSem; + + private: + LoginView *loginView; + bool cancelled; +}; + + +// ----- Utilities ---------------------------------------------------------------------- + +void safeStringCopy(char *dest, const char *source, int destSize); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_printer.cpp b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_printer.cpp new file mode 100644 index 0000000000..eb26077b6d --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_printer.cpp @@ -0,0 +1,23 @@ +#include "beserved_transport.h" + + +BeServedTransport *transport = NULL; + +extern "C" _EXPORT void exit_transport() +{ + if (transport) + { + delete transport; + transport = NULL; + } +} + +extern "C" _EXPORT BDataIO *init_transport(BMessage *msg) +{ + transport = new BeServedTransport(msg); + + if (transport->fail()) + exit_transport(); + + return transport; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_printer.h b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_printer.h new file mode 100644 index 0000000000..daef90a173 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_printer.h @@ -0,0 +1,10 @@ +#ifndef _beserved_printer_h_ +#define _beserved_printer_h_ + +#define SPOOL_PATH "printer_file" +#define SERVER_NAME "server" +#define PRINTER_NAME "Printer Name" +#define USER_NAME "user" +#define USER_PASSWORD "password" + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_rpc.cpp b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_rpc.cpp new file mode 100644 index 0000000000..adad1772a0 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_rpc.cpp @@ -0,0 +1,651 @@ +#include "betalk.h" +#include "sysdepdefs.h" +#include "beserved_rpc.h" + +#include "netdb.h" + +#define BT_RPC_THREAD_NAME "BeServed RPC Marshaller" +#define BT_MAX_TOTAL_ATTEMPTS 4 +#define BT_ATTEMPTS_BEFORE_RESTART 2 + +bool btReconnect(bt_rpcinfo *info); +int32 btRPCReceive(void *data); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); + +void btRPCRecordCall(bt_rpccall *call); +void btRPCFreeCall(bt_rpccall *call); +void btCreateInPacket(bt_rpccall *call, char *buffer, unsigned int length); +void btDestroyInPacket(bt_inPacket *packet); + +bt_rpccall *rootCall; +sem_id callSem; +sem_id connectSem; +int32 nextXID = 1; + + +void btRPCInit(bt_rpcinfo *info) +{ + info->s = INVALID_SOCKET; + info->rpcThread = 0; + info->quitXID = 0; + + callSem = create_sem(1, "rpcCall"); +// set_sem_owner(callSem, B_SYSTEM_TEAM); + + connectSem = create_sem(1, "rpcConnection"); +// set_sem_owner(connectSem, B_SYSTEM_TEAM); + + info->rpcThread = spawn_thread(btRPCReceive, BT_RPC_THREAD_NAME, B_NORMAL_PRIORITY, info); + resume_thread(info->rpcThread); +} + +void btRPCClose(bt_rpcinfo *info) +{ + if (info->rpcThread > 0) + { + status_t exitVal; + wait_for_thread(info->rpcThread, &exitVal); + } + + // Close the socket used for all file system RPC communications, + // now that we know the RPC recipient thread is dead. + closesocket(info->s); + + delete_sem(connectSem); + delete_sem(callSem); +} + +int btRecvMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesRead = 0; + do + { + int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags); + if (bytes == -1) + return -1; + + bytesRead += bytes; + } while (bytesRead < dataLen); + + return bytesRead; +} + +int btRecv(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = recv(sock, data, dataLen, flags); + if (bytes == 0) + return -1; + else if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +int btSendMsg(int sock, void *data, int dataLen, int flags) +{ + int bytesSent = 0; + do + { + int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags); + if (bytes == -1) + return -1; + + bytesSent += bytes; + } while (bytesSent < dataLen); + + return bytesSent; +} + +int btSend(int sock, void *data, int dataLen, int flags) +{ + int bytes; + + for (;;) + { + bytes = send(sock, data, dataLen, flags); + if (bytes == -1) + if (errno == EINTR) + continue; + else + return -1; + else + break; + } + + return bytes; +} + +int32 btRPCReceive(void *data) +{ + bt_rpcinfo *info = (bt_rpcinfo *) data; + bt_rpccall *call; + char signature[20], *buffer; + int32 xid, length, sigLen; + int bytes; + bool failure = false; + + while (info->s == INVALID_SOCKET) + snooze(100); + + int sock = info->s; + +#ifdef BONE_VERSION + fd_set sockSet; + struct timeval timeout; + + FD_ZERO(&sockSet); + timeout.tv_sec = 30; + timeout.tv_usec = 0; +#endif + + while (!failure) + { +#ifdef BONE_VERSION + FD_SET(sock, &sockSet); + select(sock + 1, &sockSet, NULL, NULL, &timeout); + + if (FD_ISSET(sock, &sockSet)) + { +#endif + + // Receive the signature. If a socket error occurs, break out of the loop and + // effectively exit this thread because the socket is closed. + sigLen = strlen(BT_RPC_SIGNATURE); + memset(signature, 0, sigLen); + if (btRecvMsg(sock, signature, sigLen, 0) == -1) + break; + + // Make sure the signature is correct. Otherwise, ignore it and start over. + signature[sigLen] = 0; + if (strcmp(signature, BT_RPC_SIGNATURE)) + continue; + + // Now read the transaction id (XID) and the length of the packet body. + bytes = btRecvMsg(sock, &xid, sizeof(int32), 0); + if (bytes > 0) + bytes = btRecvMsg(sock, &length, sizeof(int32), 0); + + xid = B_LENDIAN_TO_HOST_INT32(xid); + length = B_LENDIAN_TO_HOST_INT32(length); + if (length <= 0 || length >= BT_RPC_MAX_PACKET_SIZE) + continue; + + buffer = (char *) malloc(length + 1); + if (!buffer) + continue; + + // Read the remainder of the packet. + if (btRecvMsg(sock, buffer, length, 0) == -1) + failure = true; + + buffer[length] = 0; + + while (acquire_sem(callSem) == B_INTERRUPTED); + + call = rootCall; + while (call) + { + if (call->xid == xid) + { + btCreateInPacket(call, buffer, length); + release_sem(call->sem); + break; + } + + call = call->next; + } + + release_sem(callSem); + + // The originating RPC call was not found. This is probably not a very + // good sign. + if (!call) + free(buffer); + + // If a valid quit XID has been defined, and it's equal to the current + // XID, quit. + if (info->quitXID) + if (info->quitXID == xid) + break; + +#ifdef BONE_VERSION + } +#endif + + } +} + +void btCreateInPacket(bt_rpccall *call, char *buffer, unsigned int length) +{ + bt_inPacket *packet; + + packet = (bt_inPacket *) malloc(sizeof(bt_inPacket)); + if (!packet) + return; + + packet->buffer = buffer; + packet->length = length; + packet->offset = 0; + + call->inPacket = packet; +} + +void btDestroyInPacket(bt_inPacket *packet) +{ + if (packet) + { + if (packet->buffer) + free(packet->buffer); + + free(packet); + } +} + +void btRPCRecordCall(bt_rpccall *call) +{ + bt_rpccall *curCall, *lastCall; + + while (acquire_sem(callSem) == B_INTERRUPTED); + + curCall = lastCall = rootCall; + while (curCall) + { + lastCall = curCall; + curCall = curCall->next; + } + + call->next = NULL; + call->prev = lastCall; + + if (lastCall == NULL) + rootCall = call; + else + lastCall->next = call; + + release_sem(callSem); +} + +// btRPCRemoveCall() +// +void btRPCRemoveCall(bt_rpccall *call) +{ + if (call) + { + if (call->sem > 0) + delete_sem(call->sem); + + while (acquire_sem(callSem) == B_INTERRUPTED); + + // Make this entry's predecessor point to its successor. + if (call->prev) + call->prev->next = call->next; + + // Make this entry's successor point to its predecessor. + if (call->next) + call->next->prev = call->prev; + + // If we just deleted the root node of the list, then the next node + // has become the root. + if (call == rootCall) + rootCall = call->next; + + release_sem(callSem); + + // Now we can release the memory allocated for this packet. + btDestroyInPacket(call->inPacket); + free(call); + } +} + +// btConnect() +// +int btConnect(bt_rpcinfo *info, unsigned int serverIP, int port) +{ + struct sockaddr_in serverAddr; + int session, addrLen; +#ifdef BONE_VERSION + int flags; +#endif + + info->serverIP = serverIP; + info->serverPort = port; + + // Store the length of the socket addressing structure for accept(). + addrLen = sizeof(struct sockaddr_in); + + // Initialize the server address structure. + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_port = htons(port); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(serverIP); + + // Create a new socket to receive incoming requests. + session = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (session == INVALID_SOCKET) + return INVALID_SOCKET; + + // Bind that socket to the address constructed above. + if (connect(session, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) + return INVALID_SOCKET; + + // Enabled periodic keep-alive messages, so we stay connected during times of + // no activity. This isn't supported by ksocketd, only in BONE. :-( +#ifdef BONE_VERSION + flags = 1; + setsockopt(session, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags)); +#endif + + return session; +} + +void btDisconnect(bt_rpcinfo *info) +{ + bt_outPacket *packet; + bt_rpccall *call; + + packet = btRPCPutHeader(BT_CMD_QUIT, 0, 0); + call = btRPCInvoke(info, packet, true); + if (call) + btRPCRemoveCall(call); +} + +bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length) +{ + bt_outPacket *packet; + + packet = (bt_outPacket *) malloc(sizeof(bt_outPacket)); + if (!packet) + return NULL; + + packet->size = BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) malloc(packet->size); + packet->length = 0; + + if (!packet->buffer) + { + free(packet); + return NULL; + } + + strcpy(packet->buffer, BT_RPC_SIGNATURE); + packet->length += strlen(BT_RPC_SIGNATURE); + +// btRPCPutChar(packet, BT_RPC_VERSION_HI); +// btRPCPutChar(packet, BT_RPC_VERSION_LO); + btRPCPutInt32(packet, 7 + (8 * argc) + length); + btRPCPutChar(packet, command); + btRPCPutChar(packet, argc); + + return packet; +} + +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length) +{ + btRPCPutInt32(packet, type); + btRPCPutInt32(packet, length); + btRPCPutBinary(packet, data, length); +} + +bt_rpccall *btRPCInvoke(bt_rpcinfo *info, bt_outPacket *packet, bool lastPkt) +{ + status_t result; + bt_rpccall *call; + int attempts; + bool failure; + + call = (bt_rpccall *) malloc(sizeof(bt_rpccall)); + if (!call) + return NULL; + + attempts = 0; + + call->inPacket = NULL; + call->xid = atomic_add(&nextXID, 1); + if ((call->sem = create_sem(0, "rpc call")) < B_OK) + { + free(call); + return NULL; + } + + btRPCRecordCall(call); + + btRPCPutInt32(packet, call->xid); + btRPCPutChar(packet, BT_CMD_TERMINATOR); + + // If this is the last RPC packet that will be transmitted, store + // its XID so the RPC recipient thread will know when to quit. + if (lastPkt) + info->quitXID = call->xid; + +doSend: + failure = false; + if (btSendMsg(info->s, packet->buffer, packet->length, 0) == -1) + failure = true; + + if (!failure) + do + { + result = acquire_sem_etc(call->sem, 1, B_RELATIVE_TIMEOUT, 2500000); + } + while (result == B_INTERRUPTED); + + if (failure || result == B_TIMED_OUT) + { + attempts++; + if (attempts >= BT_MAX_TOTAL_ATTEMPTS) + { + free(packet->buffer); + free(packet); + btRPCRemoveCall(call); + return NULL; + } + else if (attempts == BT_ATTEMPTS_BEFORE_RESTART) + btReconnect(info); + + goto doSend; + } + + free(packet->buffer); + free(packet); + return call; +} + +bool btReconnect(bt_rpcinfo *info) +{ + static int counter = 0; + int curCount = counter; + bool connected = true; + + while (acquire_sem(connectSem) == B_INTERRUPTED); + + if (curCount == counter) + { + connected = false; + + closesocket(info->s); + if (info->rpcThread > 0) + kill_thread(info->rpcThread); + + info->s = btConnect(info, info->serverIP, info->serverPort); + if (info->s != INVALID_SOCKET) + { + info->rpcThread = spawn_thread(btRPCReceive, BT_RPC_THREAD_NAME, B_NORMAL_PRIORITY, info); + resume_thread(info->rpcThread); + connected = true; + } + + counter++; + } + + release_sem(connectSem); + return connected; +} + +void btRPCGrowPacket(bt_outPacket *packet, int bytes) +{ + if (packet->length + bytes > packet->size) + { + int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; + packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); + packet->size += growth; + } +} + +unsigned int btRPCGetInt32(bt_inPacket *packet) +{ + int32 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +int64 btRPCGetInt64(bt_inPacket *packet) +{ + int64 value; + + if (packet->offset < packet->length) + value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); + else + value = 0; + + packet->offset += sizeof(value); + return value; +} + +char *btRPCGetNewString(bt_inPacket *packet) +{ + char *str; + unsigned int bytes; + + if (packet->offset >= packet->length) + return NULL; + + bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (!bytes) + return NULL; + + str = (char *) malloc(bytes + 1); + if (!str) + return NULL; + + memcpy(str, &packet->buffer[packet->offset], bytes); + str[bytes] = 0; + + packet->offset += bytes; + + return str; +} + +int btRPCGetString(bt_inPacket *packet, char *buffer, int length) +{ + unsigned int bytes; + + if (packet->offset >= packet->length) + return 0; + + bytes = B_LENDIAN_TO_HOST_INT64(*((int32 *) &packet->buffer[packet->offset])); + packet->offset += sizeof(bytes); + if (!bytes) + return 0L; + + if (length < bytes) + return ERANGE; + + memcpy(buffer, &packet->buffer[packet->offset], bytes); + packet->offset += bytes; + return bytes; +} + +void btRPCPutChar(bt_outPacket *packet, char value) +{ + btRPCGrowPacket(packet, sizeof(value)); + packet->buffer[packet->length] = value; + packet->length += sizeof(value); +} + +void btRPCPutInt32(bt_outPacket *packet, int32 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); + packet->length += sizeof(value); +} + +void btRPCPutInt64(bt_outPacket *packet, int64 value) +{ + btRPCGrowPacket(packet, sizeof(value)); + *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); + packet->length += sizeof(value); +} + +void btRPCPutString(bt_outPacket *packet, char *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, sizeof(length) + length); + btRPCPutInt32(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) +{ + if (packet && buffer) + { + btRPCGrowPacket(packet, length); + memcpy(&packet->buffer[packet->length], buffer, length); + packet->length += length; + } +} + +int btRPCGetStat(bt_inPacket *packet, struct stat *st) +{ + st->st_dev = 0; + st->st_nlink = btRPCGetInt32(packet); + st->st_uid = btRPCGetInt32(packet); + st->st_gid = btRPCGetInt32(packet); + st->st_size = btRPCGetInt64(packet); + st->st_blksize = btRPCGetInt32(packet); + st->st_rdev = btRPCGetInt32(packet); + st->st_ino = btRPCGetInt64(packet); + st->st_mode = btRPCGetInt32(packet); + st->st_atime = btRPCGetInt32(packet); + st->st_mtime = btRPCGetInt32(packet); + st->st_ctime = btRPCGetInt32(packet); +} + +void btRPCPutStat(bt_outPacket *packet, struct stat *st) +{ + if (packet && st) + { + btRPCPutInt32(packet, (int) st->st_nlink); + btRPCPutInt32(packet, (int) st->st_uid); + btRPCPutInt32(packet, (int) st->st_gid); + btRPCPutInt64(packet, (int64) st->st_size); + btRPCPutInt32(packet, (int) st->st_blksize); + btRPCPutInt32(packet, (int) st->st_rdev); + btRPCPutInt64(packet, (int64) st->st_ino); + btRPCPutInt32(packet, (int) st->st_mode); + btRPCPutInt32(packet, (int) st->st_atime); + btRPCPutInt32(packet, (int) st->st_mtime); + btRPCPutInt32(packet, (int) st->st_ctime); + } +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_rpc.h b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_rpc.h new file mode 100644 index 0000000000..fded448859 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_rpc.h @@ -0,0 +1,9 @@ +#include "betalk.h" + +int btConnect(bt_rpcinfo *info, unsigned int serverIP, int port); +void btDisconnect(bt_rpcinfo *info); +void btRPCInit(bt_rpcinfo *info); +void btRPCClose(bt_rpcinfo *info); + +bt_rpccall *btRPCInvoke(bt_rpcinfo *info, bt_outPacket *packet, bool lastPkt); +void btRPCRemoveCall(bt_rpccall *call); diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.cpp b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.cpp new file mode 100644 index 0000000000..b605f16041 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.cpp @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "betalk.h" +#include "beserved_transport.h" +#include "beserved_printer.h" +#include "beserved_rpc.h" +#include "transport_rpc.h" + +#include "LoginPanel.h" +#include "BlowFish.h" + +#define SPOOL_FILE_TYPE "application/x-vnd.Be.printer-spool" + + +#if (!__MWERKS__ || defined(WIN32)) +using namespace std; +#else +#define std +#endif + +BeServedTransport::BeServedTransport(BMessage *msg) : + BDataIO() +{ + hostent *ent; + char jobName[100], errorMsg[256]; + + server[0] = 0; + printerName[0] = 0; + file[0] = 0; + user[0] = 0; + password[0] = 0; + jobId = 0; + error = true; + + const char *spool_path = msg->FindString(SPOOL_PATH); + if (spool_path && *spool_path) + { + dir.SetTo(spool_path); + + dir.ReadAttr(SERVER_NAME, B_STRING_TYPE, 0, server, sizeof(server)); + dir.ReadAttr(PRINTER_NAME, B_STRING_TYPE, 0, printerName, sizeof(printerName)); + dir.ReadAttr(USER_NAME, B_STRING_TYPE, 0, user, sizeof(user)); + dir.ReadAttr(USER_PASSWORD, B_STRING_TYPE, 0, password, sizeof(password)); + + strcpy(jobName, "BeServed Print Job"); + fs.close(); + + // Get the IP address of the server. + ent = gethostbyname(server); + if (ent == NULL) + { + sprintf(errorMsg, "The server %s, which hosts printer %s, cannot be found on the network.", server, printerName); + BAlert *alert = new BAlert("", errorMsg, "OK"); + alert->Go(); + return; + } + + unsigned int serverIP = ntohl(*((unsigned int *) ent->h_addr)); + + // Initialize the RPC system. + btRPCInit(&info); + + // Connect to the remote host. + info.s = btConnect(&info, serverIP, BT_TCPIP_PORT); + if (info.s != INVALID_SOCKET) + { + int result; + + // Try to start the new print job. If we get an access denied message, we may need + // to query for new credentials (permissions may have changed on the server since our + // last print job). Keep asking for a new username/password until we either get a + // successful authentication or the user cancels. + while (true) + { + result = btStartPrintJob(&info, printerName, user, password, jobName, &serverJobId); + if (result != EACCES) + break; + else if (!getNewCredentials()) + break; + } + + if (result != B_OK) + { + BAlert *alert = new BAlert("", "Your print job could not be started. This network printer may no longer be available, or you may not have permission to use it.", "OK"); + alert->Go(); + } + else + error = false; + } + else + { + sprintf(errorMsg, "The server %s, which hosts printer %s, is not responding.", server, printerName); + BAlert *alert = new BAlert("", errorMsg, "OK"); + alert->Go(); + } + } +} + +BeServedTransport::~BeServedTransport() +{ + // Now that all the data has been transmitted for the print job, start printing by + // committing the job on the server. This ends local responsibility for the task. + // Then it's up to the server. + btCommitPrintJob(&info, printerName, serverJobId); + + // End our connection with the remote host and close the RPC system. + btDisconnect(&info); + btRPCClose(&info); +} + +ssize_t BeServedTransport::Read(void *, size_t) +{ + return 0; +} + +ssize_t BeServedTransport::Write(const void *buffer, size_t size) +{ + if (size > 0) + if (btPrintJobData(&info, printerName, serverJobId, (char *) buffer, size) != B_OK) + return 0; + + return size; +} + +bool BeServedTransport::getNewCredentials() +{ + blf_ctx ctx; + int length; + + BRect frame(0, 0, LOGIN_PANEL_WIDTH, LOGIN_PANEL_HEIGHT); + LoginPanel *login = new LoginPanel(frame, server, printerName, false); + login->Center(); + status_t loginExit; + wait_for_thread(login->Thread(), &loginExit); + if (login->IsCancelled()) + return false; + + // Copy the user name. + strcpy(user, login->user); + + // Copy the user name and password supplied in the authentication dialog. + sprintf(password, "%-*s%-*s", B_FILE_NAME_LENGTH, printerName, MAX_USERNAME_LENGTH, login->user); + length = strlen(password); + assert(length == BT_AUTH_TOKEN_LENGTH); + + password[length] = 0; + blf_key(&ctx, (unsigned char *) login->md5passwd, strlen(login->md5passwd)); + blf_enc(&ctx, (unsigned long *) password, length / 4); + + dir.WriteAttr(USER_NAME, B_STRING_TYPE, 0, user, sizeof(user)); + dir.WriteAttr(USER_PASSWORD, B_STRING_TYPE, 0, password, sizeof(password)); + + return true; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.cpp-old b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.cpp-old new file mode 100644 index 0000000000..b4743cb71f --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.cpp-old @@ -0,0 +1,203 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "betalk.h" +#include "beserved_transport.h" +#include "beserved_printer.h" +#include "beserved_rpc.h" +#include "transport_rpc.h" + +#include "LoginPanel.h" +#include "BlowFish.h" + +#define SPOOL_FILE_TYPE "application/x-vnd.Be.printer-spool" + + +#if (!__MWERKS__ || defined(WIN32)) +using namespace std; +#else +#define std +#endif + +BeServedTransport::BeServedTransport(BMessage *msg) + : BDataIO() +{ + server[0] = 0; + printerName[0] = 0; + file[0] = 0; + user[0] = 0; + password[0] = 0; + jobId = 0; + error = false; + + const char *spool_path = msg->FindString(SPOOL_PATH); + if (spool_path && *spool_path) + { + dir.SetTo(spool_path); + + dir.ReadAttr(SERVER_NAME, B_STRING_TYPE, 0, server, sizeof(server)); + dir.ReadAttr(PRINTER_NAME, B_STRING_TYPE, 0, printerName, sizeof(printerName)); + dir.ReadAttr(USER_NAME, B_STRING_TYPE, 0, user, sizeof(user)); + dir.ReadAttr(USER_PASSWORD, B_STRING_TYPE, 0, password, sizeof(password)); + + do + { + sprintf(file, "%s/%lx-%ld", spool_path, time(NULL), jobId++); + } while (access(file, 0) == 0); + + fs.open(file, ios::in | ios::out | ios::binary | ios::trunc); + if (fs.good()) + return; + } + + error = true; +} + +BeServedTransport::~BeServedTransport() +{ + bt_rpcinfo info; + hostent *ent; + char jobName[100], msg[256], *serverJobId, *buffer; + int bytes; + + strcpy(jobName, "BeServed Print Job"); + fs.close(); + + // Get the IP address of the server. + ent = gethostbyname(server); + if (ent == NULL) + { + sprintf(msg, "The server %s, which hosts printer %s, cannot be found on the network.", server, printerName); + BAlert *alert = new BAlert("", msg, "OK"); + alert->Go(); + remove(file); + return; + } + + unsigned int serverIP = ntohl(*((unsigned int *) ent->h_addr)); + buffer = new char [BT_MAX_IO_BUFFER + 10]; + + // Initialize the RPC system. + btRPCInit(&info); + + // Connect to the remote host. + info.s = btConnect(&info, serverIP, BT_TCPIP_PORT); + if (info.s != INVALID_SOCKET) + { + int error; + + // Try to start the new print job. If we get an access denied message, we may need + // to query for new credentials (permissions may have changed on the server since our + // last print job). Keep asking for a new username/password until we either get a + // successful authentication or the user cancels. + while (true) + { + error = btStartPrintJob(&info, printerName, user, password, jobName, &serverJobId); + if (error != EACCES) + break; + else if (!getNewCredentials()) + break; + } + + // If we didn't receive an error, go ahead and read the file in 8K chunks. Send each + // chunk through the RPC protocol, aborting if an error occurs. + if (error == B_OK) + { + FILE *fp = fopen(file, "rb"); + if (fp) + { + do + { + bytes = fread(buffer, 1, BT_MAX_IO_BUFFER, fp); + if (bytes > 0) + { + buffer[bytes] = 0; + if (btPrintJobData(&info, printerName, serverJobId, buffer, bytes) != B_OK) + break; + } + } while (bytes > 0); + + fclose(fp); + } + + // Now that all the data has been transmitted for the print job, start printing by + // committing the job on the server. This ends local responsibility for the task. + // Then it's up to the server. + btCommitPrintJob(&info, printerName, serverJobId); + } + else + { + BAlert *alert = new BAlert("", "Your print job could not be started. This network printer may no longer be available, or you may not have permission to use it.", "OK"); + alert->Go(); + } + + // End our connection with the remote host. + btDisconnect(&info); + } + else + { + sprintf(msg, "The server %s, which hosts printer %s, is not responding.", server, printerName); + BAlert *alert = new BAlert("", msg, "OK"); + alert->Go(); + } + + // Shut down the RPC system. + btRPCClose(&info); + + // Clean up. + delete [] buffer; + remove(file); +} + +ssize_t BeServedTransport::Read(void *, size_t) +{ + return 0; +} + +ssize_t BeServedTransport::Write(const void *buffer, size_t size) +{ + if (!fs.write(buffer, size)) + { + error = true; + return 0; + } + + return size; +} + +bool BeServedTransport::getNewCredentials() +{ + blf_ctx ctx; + int length; + + BRect frame(0, 0, LOGIN_PANEL_WIDTH, LOGIN_PANEL_HEIGHT); + LoginPanel *login = new LoginPanel(frame, server, printerName, false); + login->Center(); + status_t loginExit; + wait_for_thread(login->Thread(), &loginExit); + if (login->IsCancelled()) + return false; + + // Copy the user name. + strcpy(user, login->user); + + // Copy the user name and password supplied in the authentication dialog. + sprintf(password, "%-*s%-*s", B_FILE_NAME_LENGTH, printerName, MAX_USERNAME_LENGTH, login->user); + length = strlen(password); + assert(length == BT_AUTH_TOKEN_LENGTH); + + password[length] = 0; + blf_key(&ctx, (unsigned char *) login->md5passwd, strlen(login->md5passwd)); + blf_enc(&ctx, (unsigned long *) password, length / 4); + + dir.WriteAttr(USER_NAME, B_STRING_TYPE, 0, user, sizeof(user)); + dir.WriteAttr(USER_PASSWORD, B_STRING_TYPE, 0, password, sizeof(password)); + + return true; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.h b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.h new file mode 100644 index 0000000000..ba244ec3dd --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.h @@ -0,0 +1,59 @@ +#ifndef _beserved_transport_h_ +#define _beserved_transport_h_ + +#include +#include +#include +#include +#include + +#include "betalk.h" + + +#if (!__MWERKS__ || defined(WIN32)) +using namespace std; +#else +#define std +#endif + +class BeServedTransport : public BDataIO +{ +public: + BeServedTransport(BMessage *msg); + virtual ~BeServedTransport(); + virtual ssize_t Read(void *buffer, size_t size); + virtual ssize_t Write(const void *buffer, size_t size); + + bool getNewCredentials(); + + bool operator !() const; + bool fail() const; + +private: + char server[256]; + char printerName[256]; + char *serverJobId; + + BDirectory dir; + char file[B_PATH_NAME_LENGTH]; + bt_rpcinfo info; + + char user[MAX_USERNAME_LENGTH + 1]; + char password[BT_AUTH_TOKEN_LENGTH * 2 + 1]; + + int32 jobId; + fstream fs; + bool error; +}; + +inline bool BeServedTransport::fail() const +{ + return error; +} + +inline bool BeServedTransport::operator !() const +{ + return fail(); +} + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.h-old b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.h-old new file mode 100644 index 0000000000..329ee508f2 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport.h-old @@ -0,0 +1,57 @@ +#ifndef _beserved_transport_h_ +#define _beserved_transport_h_ + +#include +#include +#include +#include +#include + +#include "betalk.h" + + +#if (!__MWERKS__ || defined(WIN32)) +using namespace std; +#else +#define std +#endif + +class BeServedTransport : public BDataIO +{ +public: + BeServedTransport(BMessage *msg); + virtual ~BeServedTransport(); + virtual ssize_t Read(void *buffer, size_t size); + virtual ssize_t Write(const void *buffer, size_t size); + + bool getNewCredentials(); + + bool operator !() const; + bool fail() const; + +private: + char server[256]; + char printerName[256]; + + BDirectory dir; + char file[B_PATH_NAME_LENGTH]; + + char user[MAX_USERNAME_LENGTH + 1]; + char password[BT_AUTH_TOKEN_LENGTH * 2 + 1]; + + int32 jobId; + fstream fs; + bool error; +}; + +inline bool BeServedTransport::fail() const +{ + return error; +} + +inline bool BeServedTransport::operator !() const +{ + return fail(); +} + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport_BONE-x86.proj b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport_BONE-x86.proj new file mode 100644 index 0000000000..c63419e586 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport_BONE-x86.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport_x86.proj b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport_x86.proj new file mode 100644 index 0000000000..449c9e91f0 Binary files /dev/null and b/src/tests/add-ons/kernel/file_systems/beserved/transport/beserved_transport_x86.proj differ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/betalk.h b/src/tests/add-ons/kernel/file_systems/beserved/transport/betalk.h new file mode 100644 index 0000000000..af38d0d926 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/betalk.h @@ -0,0 +1,252 @@ +#ifndef _BETALK_H_ +#define _BETALK_H_ + +// BeOS-specific includes +#include "TypeConstants.h" +#include "Errors.h" +#include "OS.h" +#include "fs_attr.h" +#include "fs_query.h" +#include "fs_index.h" +#include "Mime.h" +#include "netdb.h" + +// POSIX includes +#include "stdio.h" +#include "dirent.h" +#include "malloc.h" +#include "string.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "errno.h" +#include "socket.h" +#include "ctype.h" + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (int)(~0) +#endif + +#define BT_TCPIP_PORT 9092 +#define BT_QUERYHOST_PORT 9093 +#define BT_BESURE_PORT 9094 + +#define BT_CMD_TERMINATOR 13 +#define BT_CMD_PREMOUNT 0 +#define BT_CMD_MOUNT 1 +#define BT_CMD_FSINFO 2 +#define BT_CMD_LOOKUP 3 +#define BT_CMD_STAT 4 +#define BT_CMD_READDIR 5 +#define BT_CMD_READ 6 +#define BT_CMD_WRITE 7 +#define BT_CMD_CREATE 8 +#define BT_CMD_TRUNCATE 9 +#define BT_CMD_MKDIR 10 +#define BT_CMD_RMDIR 11 +#define BT_CMD_RENAME 12 +#define BT_CMD_UNLINK 13 +#define BT_CMD_READLINK 14 +#define BT_CMD_SYMLINK 15 +#define BT_CMD_WSTAT 16 +#define BT_CMD_READATTRIB 50 +#define BT_CMD_WRITEATTRIB 51 +#define BT_CMD_READATTRIBDIR 52 +#define BT_CMD_REMOVEATTRIB 53 +#define BT_CMD_STATATTRIB 54 +#define BT_CMD_READINDEXDIR 60 +#define BT_CMD_CREATEINDEX 61 +#define BT_CMD_REMOVEINDEX 62 +#define BT_CMD_STATINDEX 63 +#define BT_CMD_READQUERY 70 +#define BT_CMD_COMMIT 80 +#define BT_CMD_PRINTJOB_NEW 200 +#define BT_CMD_PRINTJOB_DATA 201 +#define BT_CMD_PRINTJOB_COMMIT 202 +#define BT_CMD_AUTHENTICATE 210 +#define BT_CMD_QUIT 255 + +#define BT_CMD_AUTH 1 +#define BT_CMD_READUSERS 2 +#define BT_CMD_READGROUPS 3 +#define BT_CMD_WHICHGROUPS 4 + +#define BT_REQ_HOST_PROBE 1 +#define BT_REQ_SHARE_PROBE 2 +#define BT_REQ_HOST_INFO 3 +#define BT_REQ_HOST_USERS 4 +#define BT_REQ_AUTH_TYPES 5 + +// The different types of network resources supported by BeServed. +#define BT_SHARED_NULL 0 +#define BT_SHARED_FOLDER 1 +#define BT_SHARED_PRINTER 2 + +#define BT_PRINTER_PCL3 0 +#define BT_PRINTER_POSTSCRIPT 1 +#define BT_PRITNER_INKJET 2 + +#define BT_AUTH_REQ_CONNECT 1 +#define BT_AUTH_REQ_USERS 2 + +#define BT_AUTH_NONE 0 +#define BT_AUTH_BESURE 1 + +#define BT_RIGHTS_READ 0x00000001 +#define BT_RIGHTS_WRITE 0x00000002 +#define BT_RIGHTS_PRINT 0x00000004 + +#define BT_RPC_SIGNATURE "btRPC" +#define BT_RPC_VERSION_HI 0 +#define BT_RPC_VERSION_LO 1 + +#define BT_MAX_IO_BUFFER 32768 +#define BT_MAX_ATTR_BUFFER 256 +#define BT_RPC_MIN_PACKET_SIZE 128 +#define BT_RPC_MAX_PACKET_SIZE (BT_MAX_IO_BUFFER + 1024) + +#define BT_TOKEN_SHARE 1 +#define BT_TOKEN_AS 2 +#define BT_TOKEN_SET 3 +#define BT_TOKEN_READ 4 +#define BT_TOKEN_WRITE 5 +#define BT_TOKEN_READWRITE 6 +#define BT_TOKEN_PROMISCUOUS 7 +#define BT_TOKEN_ON 8 +#define BT_TOKEN_TO 9 +#define BT_TOKEN_AUTHENTICATE 10 +#define BT_TOKEN_WITH 11 +#define BT_TOKEN_GROUP 12 +#define BT_TOKEN_PRINTER 13 +#define BT_TOKEN_PRINT 14 +#define BT_TOKEN_IS 15 +#define BT_TOKEN_SPOOLED 16 +#define BT_TOKEN_DEVICE 17 +#define BT_TOKEN_TYPE 18 +#define BT_TOKEN_COMMA 200 +#define BT_TOKEN_QUOTE 201 +#define BT_TOKEN_STRING 202 +#define BT_TOKEN_NUMBER 203 +#define BT_TOKEN_ERROR 255 + +#define isValid(c) ((c)=='.' || (c)=='_' || (c)=='-' || (c)=='/' || (c)=='\\' || (c)==':' || (c)=='&' || (c)=='\'') + +#define MAX_COMMAND_ARGS 10 +#define MAX_NAME_LENGTH 32 +#define MAX_KEY_LENGTH MAX_NAME_LENGTH +#define MAX_USERNAME_LENGTH MAX_NAME_LENGTH +#define MAX_GROUPNAME_LENGTH MAX_NAME_LENGTH +#define BT_AUTH_TOKEN_LENGTH (B_FILE_NAME_LENGTH + MAX_USERNAME_LENGTH) +#define MAX_DESC_LENGTH 64 +#define MAX_GROUPS_PER_USER 80 + +typedef struct +{ + char signature[6]; + uint8 command; + char share[MAX_NAME_LENGTH + 1]; +} bt_request; + +typedef struct +{ + uint32 type; + uint32 subType; + char name[B_FILE_NAME_LENGTH + 1]; +} bt_resource; + +typedef struct +{ + char system[B_FILE_NAME_LENGTH]; + char beServed[B_FILE_NAME_LENGTH]; + char platform[B_FILE_NAME_LENGTH]; + int cpus; + int connections; + int maxConnections; +} bt_hostinfo; + +typedef struct +{ + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; +} bt_fsinfo; + +typedef struct +{ + unsigned int size; + unsigned int length; + char *buffer; +} bt_outPacket; + +typedef struct +{ + unsigned int length; + unsigned int offset; + char *buffer; +} bt_inPacket; + +typedef struct rpcCall +{ + unsigned int nsid; + unsigned int xid; + sem_id sem; + bt_inPacket *inPacket; + bool finished; + struct rpcCall *next; + struct rpcCall *prev; +} bt_rpccall; + +typedef struct rpcInfo +{ + thread_id rpcThread; + int32 quitXID; + + uint32 serverIP; + int32 serverPort; + int s; +} bt_rpcinfo; + +#define BT_COOKIE_SIZE 4 + +typedef struct btCookie +{ + char opaque[BT_COOKIE_SIZE]; + bt_inPacket inPacket; + bool lpbCache; + bool eof; +} btCookie; + +typedef struct btQueryCookie +{ + char opaque[BT_COOKIE_SIZE]; + char *query; +} btQueryCookie; + +// RPC Operations +unsigned char btRPCGetChar(bt_inPacket *packet); +unsigned int btRPCGetInt32(bt_inPacket *packet); +int64 btRPCGetInt64(bt_inPacket *packet); +char * btRPCGetNewString(bt_inPacket *packet); +int btRPCGetString(bt_inPacket *packet, char *buffer, int length); +int btRPCGetStat(bt_inPacket *packet, struct stat *st); +bt_outPacket * btRPCPutHeader(unsigned char command, unsigned char argc, int32 length); +void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length); +void btRPCPutChar(bt_outPacket *packet, char value); +void btRPCPutInt32(bt_outPacket *packet, int32 value); +void btRPCPutInt64(bt_outPacket *packet, int64 value); +void btRPCPutString(bt_outPacket *packet, char *buffer, int length); +void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length); +void btRPCPutStat(bt_outPacket *packet, struct stat *st); + +void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error); +void btRPCSendAck(int client, bt_outPacket *packet); + +int btRecv(int sock, void *data, int dataLen, int flags); +int btSend(int sock, void *data, int dataLen, int flags); +int btRecvMsg(int sock, void *data, int dataLen, int flags); +int btSendMsg(int sock, void *data, int dataLen, int flags); + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/md5.h b/src/tests/add-ons/kernel/file_systems/beserved/transport/md5.h new file mode 100644 index 0000000000..4148570cd7 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/md5.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id: md5.h $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This code has some adaptations for the Ghostscript environment, but it + * will compile and run correctly in any environment with 8-bit chars and + * 32-bit ints. Specifically, it assumes that if the following are + * defined, they have the same meaning as in Ghostscript: P1, P2, P3, + * ARCH_IS_BIG_ENDIAN. + */ + +#ifdef _BUILDING_BESURE_ +#define _IMPEXP_BESURE __declspec(dllexport) +#else +#define _IMPEXP_BESURE __declspec(dllimport) +#endif + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +_IMPEXP_BESURE void md5EncodeString(const char *source, char *dest); + +/* Initialize the algorithm. */ +#ifdef P1 +void md5_init(P1(md5_state_t *pms)); +#else +void md5_init(md5_state_t *pms); +#endif + +/* Append a string to the message. */ +#ifdef P3 +void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); +#else +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +#endif + +/* Finish the message and return the digest. */ +#ifdef P2 +void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); +#else +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/sysdepdefs.h b/src/tests/add-ons/kernel/file_systems/beserved/transport/sysdepdefs.h new file mode 100644 index 0000000000..6bb4bd5051 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/sysdepdefs.h @@ -0,0 +1,10 @@ +#ifndef _SYSDEPDEFS_H_ +#define _SYSDEPDEFS_H_ + +#ifdef BONE_VERSION + +#define closesocket(s) close(s) + +#endif + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/transport_rpc.cpp b/src/tests/add-ons/kernel/file_systems/beserved/transport/transport_rpc.cpp new file mode 100644 index 0000000000..509b0e947a --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/transport_rpc.cpp @@ -0,0 +1,95 @@ +#include "betalk.h" +#include "beserved_rpc.h" + + +// btStartPrintJob() +// +int btStartPrintJob(bt_rpcinfo *info, char *printerName, char *user, char *password, char *jobName, char **jobId) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_PRINTJOB_NEW, 4, strlen(printerName) + strlen(jobName) + strlen(user) + BT_AUTH_TOKEN_LENGTH); + btRPCPutArg(outPacket, B_STRING_TYPE, printerName, strlen(printerName)); + btRPCPutArg(outPacket, B_STRING_TYPE, user, strlen(user)); + btRPCPutArg(outPacket, B_STRING_TYPE, password, BT_AUTH_TOKEN_LENGTH); + btRPCPutArg(outPacket, B_STRING_TYPE, jobName, strlen(jobName)); + call = btRPCInvoke(info, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + { + error = btRPCGetInt32(inPacket); + if (error == B_OK) + *jobId = btRPCGetNewString(inPacket); + } + + btRPCRemoveCall(call); + } + + return error; +} + +// btPrintJobData() +// +int btPrintJobData(bt_rpcinfo *info, char *printerName, char *jobId, char *data, int dataLen) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_PRINTJOB_DATA, 4, strlen(printerName) + strlen(jobId) + dataLen + 4); + btRPCPutArg(outPacket, B_STRING_TYPE, printerName, strlen(printerName)); + btRPCPutArg(outPacket, B_STRING_TYPE, jobId, strlen(jobId)); + btRPCPutArg(outPacket, B_STRING_TYPE, data, dataLen); + btRPCPutArg(outPacket, B_INT32_TYPE, &dataLen, sizeof(dataLen)); + call = btRPCInvoke(info, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} + +// btCommitPrintJob() +// +int btCommitPrintJob(bt_rpcinfo *info, char *printerName, char *jobId) +{ + bt_inPacket *inPacket; + bt_outPacket *outPacket; + bt_rpccall *call; + int error; + + error = EHOSTUNREACH; + + outPacket = btRPCPutHeader(BT_CMD_PRINTJOB_COMMIT, 2, strlen(printerName) + strlen(jobId)); + btRPCPutArg(outPacket, B_STRING_TYPE, printerName, strlen(printerName)); + btRPCPutArg(outPacket, B_STRING_TYPE, jobId, strlen(jobId)); + call = btRPCInvoke(info, outPacket, false); + + if (call) + { + inPacket = call->inPacket; + if (inPacket) + error = btRPCGetInt32(inPacket); + + btRPCRemoveCall(call); + } + + return error; +} diff --git a/src/tests/add-ons/kernel/file_systems/beserved/transport/transport_rpc.h b/src/tests/add-ons/kernel/file_systems/beserved/transport/transport_rpc.h new file mode 100644 index 0000000000..4f4ae10779 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/beserved/transport/transport_rpc.h @@ -0,0 +1,5 @@ +#include "betalk.h" + +int btStartPrintJob(bt_rpcinfo *info, char *printerName, char *user, char *password, char *jobName, char **jobId); +int btPrintJobData(bt_rpcinfo *info, char *printerName, char *jobId, char *data, int dataLen); +int btCommitPrintJob(bt_rpcinfo *info, char *printerName, char *jobId);