00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022 #include "utils/net.h"
00023
00024 struct {
00025 const char *us_errstr;
00026 enum usershare_err us_err;
00027 } us_errs [] = {
00028 {"",USERSHARE_OK},
00029 {"Malformed usershare file", USERSHARE_MALFORMED_FILE},
00030 {"Bad version number", USERSHARE_BAD_VERSION},
00031 {"Malformed path entry", USERSHARE_MALFORMED_PATH},
00032 {"Malformed comment entryfile", USERSHARE_MALFORMED_COMMENT_DEF},
00033 {"Malformed acl definition", USERSHARE_MALFORMED_ACL_DEF},
00034 {"Acl parse error", USERSHARE_ACL_ERR},
00035 {"Path not absolute", USERSHARE_PATH_NOT_ABSOLUTE},
00036 {"Path is denied", USERSHARE_PATH_IS_DENIED},
00037 {"Path not allowed", USERSHARE_PATH_NOT_ALLOWED},
00038 {"Path is not a directory", USERSHARE_PATH_NOT_DIRECTORY},
00039 {"System error", USERSHARE_POSIX_ERR},
00040 {NULL,(enum usershare_err)-1}
00041 };
00042
00043 static const char *get_us_error_code(enum usershare_err us_err)
00044 {
00045 static pstring out;
00046 int idx = 0;
00047
00048 while (us_errs[idx].us_errstr != NULL) {
00049 if (us_errs[idx].us_err == us_err) {
00050 return us_errs[idx].us_errstr;
00051 }
00052 idx++;
00053 }
00054
00055 slprintf(out, sizeof(out), "Usershare error code (0x%x)", (unsigned int)us_err);
00056 return out;
00057 }
00058
00059
00060
00061 static int net_usershare_add_usage(int argc, const char **argv)
00062 {
00063 char c = *lp_winbind_separator();
00064 d_printf(
00065 "net usershare add [-l|--long] <sharename> <path> [<comment>] [<acl>] [<guest_ok=[y|n]>]\n"
00066 "\tAdds the specified share name for this user.\n"
00067 "\t<sharename> is the new share name.\n"
00068 "\t<path> is the path on the filesystem to export.\n"
00069 "\t<comment> is the optional comment for the new share.\n"
00070 "\t<acl> is an optional share acl in the format \"DOMAIN%cname:X,DOMAIN%cname:X,....\"\n"
00071 "\t<guest_ok=y> if present sets \"guest ok = yes\" on this usershare.\n"
00072 "\t\t\"X\" represents a permission and can be any one of the characters f, r or d\n"
00073 "\t\twhere \"f\" means full control, \"r\" means read-only, \"d\" means deny access.\n"
00074 "\t\tname may be a domain user or group. For local users use the local server name "
00075 "instead of \"DOMAIN\"\n"
00076 "\t\tThe default acl is \"Everyone:r\" which allows everyone read-only access.\n"
00077 "\tAdd -l or --long to print the info on the newly added share.\n",
00078 c, c );
00079 return -1;
00080 }
00081
00082 static int net_usershare_delete_usage(int argc, const char **argv)
00083 {
00084 d_printf(
00085 "net usershare delete <sharename>\n"\
00086 "\tdeletes the specified share name for this user.\n");
00087 return -1;
00088 }
00089
00090 static int net_usershare_info_usage(int argc, const char **argv)
00091 {
00092 d_printf(
00093 "net usershare info [-l|--long] [wildcard sharename]\n"\
00094 "\tPrints out the path, comment and acl elements of shares that match the wildcard.\n"
00095 "\tBy default only gives info on shares owned by the current user\n"
00096 "\tAdd -l or --long to apply this to all shares\n"
00097 "\tOmit the sharename or use a wildcard of '*' to see all shares\n");
00098 return -1;
00099 }
00100
00101 static int net_usershare_list_usage(int argc, const char **argv)
00102 {
00103 d_printf(
00104 "net usershare list [-l|--long] [wildcard sharename]\n"\
00105 "\tLists the names of all shares that match the wildcard.\n"
00106 "\tBy default only lists shares owned by the current user\n"
00107 "\tAdd -l or --long to apply this to all shares\n"
00108 "\tOmit the sharename or use a wildcard of '*' to see all shares\n");
00109 return -1;
00110 }
00111
00112 int net_usershare_usage(int argc, const char **argv)
00113 {
00114 d_printf("net usershare add <sharename> <path> [<comment>] [<acl>] [<guest_ok=[y|n]>] to "
00115 "add or change a user defined share.\n"
00116 "net usershare delete <sharename> to delete a user defined share.\n"
00117 "net usershare info [-l|--long] [wildcard sharename] to print info about a user defined share.\n"
00118 "net usershare list [-l|--long] [wildcard sharename] to list user defined shares.\n"
00119 "net usershare help\n"\
00120 "\nType \"net usershare help <option>\" to get more information on that option\n\n");
00121
00122 net_common_flags_usage(argc, argv);
00123 return -1;
00124 }
00125
00126
00127
00128
00129 static void get_basepath(pstring basepath)
00130 {
00131 pstrcpy(basepath, lp_usershare_path());
00132 if ((basepath[0] != '\0') && (basepath[strlen(basepath)-1] == '/')) {
00133 basepath[strlen(basepath)-1] = '\0';
00134 }
00135 }
00136
00137
00138
00139
00140
00141 static int net_usershare_delete(int argc, const char **argv)
00142 {
00143 pstring us_path;
00144 char *sharename;
00145
00146 if (argc != 1) {
00147 return net_usershare_delete_usage(argc, argv);
00148 }
00149
00150 if ((sharename = strdup_lower(argv[0])) == NULL) {
00151 d_fprintf(stderr, "strdup failed\n");
00152 return -1;
00153 }
00154
00155 if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, strlen(sharename))) {
00156 d_fprintf(stderr, "net usershare delete: share name %s contains "
00157 "invalid characters (any of %s)\n",
00158 sharename, INVALID_SHARENAME_CHARS);
00159 SAFE_FREE(sharename);
00160 return -1;
00161 }
00162
00163 pstrcpy(us_path, lp_usershare_path());
00164 pstrcat(us_path, "/");
00165 pstrcat(us_path, sharename);
00166
00167 if (unlink(us_path) != 0) {
00168 d_fprintf(stderr, "net usershare delete: unable to remove usershare %s. "
00169 "Error was %s\n",
00170 us_path, strerror(errno));
00171 SAFE_FREE(sharename);
00172 return -1;
00173 }
00174 SAFE_FREE(sharename);
00175 return 0;
00176 }
00177
00178
00179
00180
00181
00182 struct file_list {
00183 struct file_list *next, *prev;
00184 const char *pathname;
00185 };
00186
00187 static struct file_list *flist;
00188
00189
00190
00191
00192 static int get_share_list(TALLOC_CTX *ctx, const char *wcard, BOOL only_ours)
00193 {
00194 SMB_STRUCT_DIR *dp;
00195 SMB_STRUCT_DIRENT *de;
00196 uid_t myuid = geteuid();
00197 struct file_list *fl = NULL;
00198 pstring basepath;
00199
00200 get_basepath(basepath);
00201 dp = sys_opendir(basepath);
00202 if (!dp) {
00203 d_fprintf(stderr, "get_share_list: cannot open usershare directory %s. Error %s\n",
00204 basepath, strerror(errno) );
00205 return -1;
00206 }
00207
00208 while((de = sys_readdir(dp)) != 0) {
00209 SMB_STRUCT_STAT sbuf;
00210 pstring path;
00211 const char *n = de->d_name;
00212
00213
00214 if (*n == '.') {
00215 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
00216 continue;
00217 }
00218 }
00219
00220 if (!validate_net_name(n, INVALID_SHARENAME_CHARS, strlen(n))) {
00221 d_fprintf(stderr, "get_share_list: ignoring bad share name %s\n",n);
00222 continue;
00223 }
00224 pstrcpy(path, basepath);
00225 pstrcat(path, "/");
00226 pstrcat(path, n);
00227
00228 if (sys_lstat(path, &sbuf) != 0) {
00229 d_fprintf(stderr, "get_share_list: can't lstat file %s. Error was %s\n",
00230 path, strerror(errno) );
00231 continue;
00232 }
00233
00234 if (!S_ISREG(sbuf.st_mode)) {
00235 d_fprintf(stderr, "get_share_list: file %s is not a regular file. Ignoring.\n",
00236 path );
00237 continue;
00238 }
00239
00240 if (only_ours && sbuf.st_uid != myuid) {
00241 continue;
00242 }
00243
00244 if (!unix_wild_match(wcard, n)) {
00245 continue;
00246 }
00247
00248
00249 fl = TALLOC_P(ctx, struct file_list);
00250 if (!fl) {
00251 return -1;
00252 }
00253 fl->pathname = talloc_strdup(ctx, n);
00254 if (!fl->pathname) {
00255 return -1;
00256 }
00257
00258 DLIST_ADD(flist, fl);
00259 }
00260
00261 sys_closedir(dp);
00262 return 0;
00263 }
00264
00265 enum us_priv_op { US_LIST_OP, US_INFO_OP};
00266
00267 struct us_priv_info {
00268 TALLOC_CTX *ctx;
00269 enum us_priv_op op;
00270 };
00271
00272
00273
00274
00275
00276 static int process_share_list(int (*fn)(struct file_list *, void *), void *priv)
00277 {
00278 struct file_list *fl;
00279 int ret = 0;
00280
00281 for (fl = flist; fl; fl = fl->next) {
00282 ret = (*fn)(fl, priv);
00283 }
00284
00285 return ret;
00286 }
00287
00288
00289
00290
00291
00292 static int info_fn(struct file_list *fl, void *priv)
00293 {
00294 SMB_STRUCT_STAT sbuf;
00295 char **lines = NULL;
00296 struct us_priv_info *pi = (struct us_priv_info *)priv;
00297 TALLOC_CTX *ctx = pi->ctx;
00298 int fd = -1;
00299 int numlines = 0;
00300 SEC_DESC *psd = NULL;
00301 pstring basepath;
00302 pstring sharepath;
00303 pstring comment;
00304 pstring acl_str;
00305 int num_aces;
00306 char sep_str[2];
00307 enum usershare_err us_err;
00308 BOOL guest_ok = False;
00309
00310 sep_str[0] = *lp_winbind_separator();
00311 sep_str[1] = '\0';
00312
00313 get_basepath(basepath);
00314 pstrcat(basepath, "/");
00315 pstrcat(basepath, fl->pathname);
00316
00317 #ifdef O_NOFOLLOW
00318 fd = sys_open(basepath, O_RDONLY|O_NOFOLLOW, 0);
00319 #else
00320 fd = sys_open(basepath, O_RDONLY, 0);
00321 #endif
00322
00323 if (fd == -1) {
00324 d_fprintf(stderr, "info_fn: unable to open %s. %s\n",
00325 basepath, strerror(errno) );
00326 return -1;
00327 }
00328
00329
00330 if (sys_fstat(fd, &sbuf) != 0) {
00331 d_fprintf(stderr, "info_fn: can't fstat file %s. Error was %s\n",
00332 basepath, strerror(errno) );
00333 close(fd);
00334 return -1;
00335 }
00336
00337 if (!S_ISREG(sbuf.st_mode)) {
00338 d_fprintf(stderr, "info_fn: file %s is not a regular file. Ignoring.\n",
00339 basepath );
00340 close(fd);
00341 return -1;
00342 }
00343
00344 lines = fd_lines_load(fd, &numlines, 10240);
00345 close(fd);
00346
00347 if (lines == NULL) {
00348 return -1;
00349 }
00350
00351
00352 us_err = parse_usershare_file(ctx, &sbuf, fl->pathname, -1, lines, numlines,
00353 sharepath,
00354 comment,
00355 &psd,
00356 &guest_ok);
00357
00358 file_lines_free(lines);
00359
00360 if (us_err != USERSHARE_OK) {
00361 d_fprintf(stderr, "info_fn: file %s is not a well formed usershare file.\n",
00362 basepath );
00363 d_fprintf(stderr, "info_fn: Error was %s.\n",
00364 get_us_error_code(us_err) );
00365 return -1;
00366 }
00367
00368 pstrcpy(acl_str, "usershare_acl=");
00369
00370 for (num_aces = 0; num_aces < psd->dacl->num_aces; num_aces++) {
00371 const char *domain;
00372 const char *name;
00373 NTSTATUS ntstatus;
00374
00375 ntstatus = net_lookup_name_from_sid(ctx, &psd->dacl->aces[num_aces].trustee, &domain, &name);
00376
00377 if (NT_STATUS_IS_OK(ntstatus)) {
00378 if (domain && *domain) {
00379 pstrcat(acl_str, domain);
00380 pstrcat(acl_str, sep_str);
00381 }
00382 pstrcat(acl_str,name);
00383 } else {
00384 fstring sidstr;
00385 sid_to_string(sidstr, &psd->dacl->aces[num_aces].trustee);
00386 pstrcat(acl_str,sidstr);
00387 }
00388 pstrcat(acl_str, ":");
00389
00390 if (psd->dacl->aces[num_aces].type == SEC_ACE_TYPE_ACCESS_DENIED) {
00391 pstrcat(acl_str, "D,");
00392 } else {
00393 if (psd->dacl->aces[num_aces].access_mask & GENERIC_ALL_ACCESS) {
00394 pstrcat(acl_str, "F,");
00395 } else {
00396 pstrcat(acl_str, "R,");
00397 }
00398 }
00399 }
00400
00401 acl_str[strlen(acl_str)-1] = '\0';
00402
00403 if (pi->op == US_INFO_OP) {
00404 d_printf("[%s]\n", fl->pathname );
00405 d_printf("path=%s\n", sharepath );
00406 d_printf("comment=%s\n", comment);
00407 d_printf("%s\n", acl_str);
00408 d_printf("guest_ok=%c\n\n", guest_ok ? 'y' : 'n');
00409 } else if (pi->op == US_LIST_OP) {
00410 d_printf("%s\n", fl->pathname);
00411 }
00412
00413 return 0;
00414 }
00415
00416
00417
00418
00419
00420 static int net_usershare_info(int argc, const char **argv)
00421 {
00422 fstring wcard;
00423 BOOL only_ours = True;
00424 int ret = -1;
00425 struct us_priv_info pi;
00426 TALLOC_CTX *ctx;
00427
00428 fstrcpy(wcard, "*");
00429
00430 if (opt_long_list_entries) {
00431 only_ours = False;
00432 }
00433
00434 switch (argc) {
00435 case 0:
00436 break;
00437 case 1:
00438 fstrcpy(wcard, argv[0]);
00439 break;
00440 default:
00441 return net_usershare_info_usage(argc, argv);
00442 }
00443
00444 strlower_m(wcard);
00445
00446 ctx = talloc_init("share_info");
00447 ret = get_share_list(ctx, wcard, only_ours);
00448 if (ret) {
00449 return ret;
00450 }
00451
00452 pi.ctx = ctx;
00453 pi.op = US_INFO_OP;
00454
00455 ret = process_share_list(info_fn, &pi);
00456 talloc_destroy(ctx);
00457 return ret;
00458 }
00459
00460
00461
00462
00463
00464 static int count_num_usershares(void)
00465 {
00466 SMB_STRUCT_DIR *dp;
00467 SMB_STRUCT_DIRENT *de;
00468 pstring basepath;
00469 int num_usershares = 0;
00470
00471 get_basepath(basepath);
00472 dp = sys_opendir(basepath);
00473 if (!dp) {
00474 d_fprintf(stderr, "count_num_usershares: cannot open usershare directory %s. Error %s\n",
00475 basepath, strerror(errno) );
00476 return -1;
00477 }
00478
00479 while((de = sys_readdir(dp)) != 0) {
00480 SMB_STRUCT_STAT sbuf;
00481 pstring path;
00482 const char *n = de->d_name;
00483
00484
00485 if (*n == '.') {
00486 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
00487 continue;
00488 }
00489 }
00490
00491 if (!validate_net_name(n, INVALID_SHARENAME_CHARS, strlen(n))) {
00492 d_fprintf(stderr, "count_num_usershares: ignoring bad share name %s\n",n);
00493 continue;
00494 }
00495 pstrcpy(path, basepath);
00496 pstrcat(path, "/");
00497 pstrcat(path, n);
00498
00499 if (sys_lstat(path, &sbuf) != 0) {
00500 d_fprintf(stderr, "count_num_usershares: can't lstat file %s. Error was %s\n",
00501 path, strerror(errno) );
00502 continue;
00503 }
00504
00505 if (!S_ISREG(sbuf.st_mode)) {
00506 d_fprintf(stderr, "count_num_usershares: file %s is not a regular file. Ignoring.\n",
00507 path );
00508 continue;
00509 }
00510 num_usershares++;
00511 }
00512
00513 sys_closedir(dp);
00514 return num_usershares;
00515 }
00516
00517
00518
00519
00520
00521 static int net_usershare_add(int argc, const char **argv)
00522 {
00523 TALLOC_CTX *ctx = NULL;
00524 SMB_STRUCT_STAT sbuf;
00525 SMB_STRUCT_STAT lsbuf;
00526 char *sharename;
00527 pstring full_path;
00528 pstring full_path_tmp;
00529 const char *us_path;
00530 const char *us_comment;
00531 const char *arg_acl;
00532 char *us_acl;
00533 char *file_img;
00534 int num_aces = 0;
00535 int i;
00536 int tmpfd;
00537 const char *pacl;
00538 size_t to_write;
00539 uid_t myeuid = geteuid();
00540 BOOL guest_ok = False;
00541 int num_usershares;
00542
00543 us_comment = "";
00544 arg_acl = "S-1-1-0:R";
00545
00546 switch (argc) {
00547 case 0:
00548 case 1:
00549 default:
00550 return net_usershare_add_usage(argc, argv);
00551 case 2:
00552 sharename = strdup_lower(argv[0]);
00553 us_path = argv[1];
00554 break;
00555 case 3:
00556 sharename = strdup_lower(argv[0]);
00557 us_path = argv[1];
00558 us_comment = argv[2];
00559 break;
00560 case 4:
00561 sharename = strdup_lower(argv[0]);
00562 us_path = argv[1];
00563 us_comment = argv[2];
00564 arg_acl = argv[3];
00565 break;
00566 case 5:
00567 sharename = strdup_lower(argv[0]);
00568 us_path = argv[1];
00569 us_comment = argv[2];
00570 arg_acl = argv[3];
00571 if (strlen(arg_acl) == 0) {
00572 arg_acl = "S-1-1-0:R";
00573 }
00574 if (!strnequal(argv[4], "guest_ok=", 9)) {
00575 return net_usershare_add_usage(argc, argv);
00576 }
00577 switch (argv[4][9]) {
00578 case 'y':
00579 case 'Y':
00580 guest_ok = True;
00581 break;
00582 case 'n':
00583 case 'N':
00584 guest_ok = False;
00585 break;
00586 default:
00587 return net_usershare_add_usage(argc, argv);
00588 }
00589 break;
00590 }
00591
00592
00593 num_usershares = count_num_usershares();
00594 if (num_usershares >= lp_usershare_max_shares()) {
00595 d_fprintf(stderr, "net usershare add: maximum number of allowed usershares (%d) reached\n",
00596 lp_usershare_max_shares() );
00597 SAFE_FREE(sharename);
00598 return -1;
00599 }
00600
00601 if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, strlen(sharename))) {
00602 d_fprintf(stderr, "net usershare add: share name %s contains "
00603 "invalid characters (any of %s)\n",
00604 sharename, INVALID_SHARENAME_CHARS);
00605 SAFE_FREE(sharename);
00606 return -1;
00607 }
00608
00609
00610 if (getpwnam(sharename)) {
00611 d_fprintf(stderr, "net usershare add: share name %s is already a valid system user name\n",
00612 sharename );
00613 SAFE_FREE(sharename);
00614 return -1;
00615 }
00616
00617
00618 get_basepath(full_path);
00619 pstrcat(full_path, "/");
00620 pstrcpy(full_path_tmp, full_path);
00621 pstrcat(full_path, sharename);
00622 pstrcat(full_path_tmp, ":tmpXXXXXX");
00623
00624
00625 if (us_path[0] != '/') {
00626 d_fprintf(stderr,"net usershare add: path %s is not an absolute path.\n",
00627 us_path);
00628 SAFE_FREE(sharename);
00629 return -1;
00630 }
00631
00632
00633 if (sys_stat(us_path, &sbuf) != 0) {
00634 d_fprintf(stderr, "net usershare add: cannot stat path %s to ensure "
00635 "this is a directory. Error was %s\n",
00636 us_path, strerror(errno) );
00637 SAFE_FREE(sharename);
00638 return -1;
00639 }
00640
00641 if (!S_ISDIR(sbuf.st_mode)) {
00642 d_fprintf(stderr, "net usershare add: path %s is not a directory.\n",
00643 us_path );
00644 SAFE_FREE(sharename);
00645 return -1;
00646 }
00647
00648
00649
00650
00651 if ((myeuid != 0) && lp_usershare_owner_only() && (myeuid != sbuf.st_uid)) {
00652 d_fprintf(stderr, "net usershare add: cannot share path %s as "
00653 "we are restricted to only sharing directories we own.\n"
00654 "\tAsk the administrator to add the line \"usershare owner only = False\" \n"
00655 "\tto the [global] section of the smb.conf to allow this.\n",
00656 us_path );
00657 SAFE_FREE(sharename);
00658 return -1;
00659 }
00660
00661
00662
00663
00664
00665 ctx = talloc_init("share_info");
00666
00667
00668 us_acl = talloc_strdup(ctx, "");
00669
00670 pacl = arg_acl;
00671 num_aces = 1;
00672
00673
00674 num_aces += count_chars(pacl,',');
00675
00676 for (i = 0; i < num_aces; i++) {
00677 DOM_SID sid;
00678 const char *pcolon = strchr_m(pacl, ':');
00679 const char *name;
00680
00681 if (pcolon == NULL) {
00682 d_fprintf(stderr, "net usershare add: malformed acl %s (missing ':').\n",
00683 pacl );
00684 talloc_destroy(ctx);
00685 SAFE_FREE(sharename);
00686 return -1;
00687 }
00688
00689 switch(pcolon[1]) {
00690 case 'f':
00691 case 'F':
00692 case 'd':
00693 case 'r':
00694 case 'R':
00695 break;
00696 default:
00697 d_fprintf(stderr, "net usershare add: malformed acl %s "
00698 "(access control must be 'r', 'f', or 'd')\n",
00699 pacl );
00700 talloc_destroy(ctx);
00701 SAFE_FREE(sharename);
00702 return -1;
00703 }
00704
00705 if (pcolon[2] != ',' && pcolon[2] != '\0') {
00706 d_fprintf(stderr, "net usershare add: malformed terminating character for acl %s\n",
00707 pacl );
00708 talloc_destroy(ctx);
00709 SAFE_FREE(sharename);
00710 return -1;
00711 }
00712
00713
00714 if ((name = talloc_strndup(ctx, pacl, pcolon - pacl)) == NULL) {
00715 d_fprintf(stderr, "talloc_strndup failed\n");
00716 talloc_destroy(ctx);
00717 SAFE_FREE(sharename);
00718 return -1;
00719 }
00720 if (!string_to_sid(&sid, name)) {
00721
00722 NTSTATUS ntstatus = net_lookup_sid_from_name(ctx, name, &sid);
00723 if (!NT_STATUS_IS_OK(ntstatus)) {
00724 d_fprintf(stderr, "net usershare add: cannot convert name \"%s\" to a SID. %s.",
00725 name, get_friendly_nt_error_msg(ntstatus) );
00726 if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_CONNECTION_REFUSED)) {
00727 d_fprintf(stderr, " Maybe smbd is not running.\n");
00728 } else {
00729 d_fprintf(stderr, "\n");
00730 }
00731 talloc_destroy(ctx);
00732 SAFE_FREE(sharename);
00733 return -1;
00734 }
00735 }
00736 us_acl = talloc_asprintf_append(us_acl, "%s:%c,", sid_string_static(&sid), pcolon[1]);
00737
00738
00739 if (pcolon[2] == ',') {
00740 pacl = &pcolon[3];
00741 }
00742 }
00743
00744
00745 us_acl[strlen(us_acl)-1] = '\0';
00746
00747 if (guest_ok && !lp_usershare_allow_guests()) {
00748 d_fprintf(stderr, "net usershare add: guest_ok=y requested "
00749 "but the \"usershare allow guests\" parameter is not enabled "
00750 "by this server.\n");
00751 talloc_destroy(ctx);
00752 SAFE_FREE(sharename);
00753 return -1;
00754 }
00755
00756
00757 tmpfd = smb_mkstemp(full_path_tmp);
00758
00759 if (tmpfd == -1) {
00760 d_fprintf(stderr, "net usershare add: cannot create tmp file %s\n",
00761 full_path_tmp );
00762 talloc_destroy(ctx);
00763 SAFE_FREE(sharename);
00764 return -1;
00765 }
00766
00767
00768 if (sys_lstat(full_path_tmp, &lsbuf) != 0) {
00769 d_fprintf(stderr, "net usershare add: cannot lstat tmp file %s\n",
00770 full_path_tmp );
00771 talloc_destroy(ctx);
00772 SAFE_FREE(sharename);
00773 return -1;
00774 }
00775
00776
00777 if (sys_fstat(tmpfd, &sbuf) != 0) {
00778 d_fprintf(stderr, "net usershare add: cannot fstat tmp file %s\n",
00779 full_path_tmp );
00780 talloc_destroy(ctx);
00781 SAFE_FREE(sharename);
00782 return -1;
00783 }
00784
00785 if (!S_ISREG(sbuf.st_mode) || sbuf.st_dev != lsbuf.st_dev || sbuf.st_ino != lsbuf.st_ino) {
00786 d_fprintf(stderr, "net usershare add: tmp file %s is not a regular file ?\n",
00787 full_path_tmp );
00788 talloc_destroy(ctx);
00789 SAFE_FREE(sharename);
00790 return -1;
00791 }
00792
00793 if (fchmod(tmpfd, 0644) == -1) {
00794 d_fprintf(stderr, "net usershare add: failed to fchmod tmp file %s to 0644n",
00795 full_path_tmp );
00796 talloc_destroy(ctx);
00797 SAFE_FREE(sharename);
00798 return -1;
00799 }
00800
00801
00802 file_img = talloc_strdup(ctx, "#VERSION 2\npath=");
00803 file_img = talloc_asprintf_append(file_img, "%s\ncomment=%s\nusershare_acl=%s\nguest_ok=%c\n",
00804 us_path, us_comment, us_acl, guest_ok ? 'y' : 'n');
00805
00806 to_write = strlen(file_img);
00807
00808 if (write(tmpfd, file_img, to_write) != to_write) {
00809 d_fprintf(stderr, "net usershare add: failed to write %u bytes to file %s. Error was %s\n",
00810 (unsigned int)to_write, full_path_tmp, strerror(errno));
00811 unlink(full_path_tmp);
00812 talloc_destroy(ctx);
00813 SAFE_FREE(sharename);
00814 return -1;
00815 }
00816
00817
00818 if (rename(full_path_tmp, full_path) != 0) {
00819 unlink(full_path_tmp);
00820 d_fprintf(stderr, "net usershare add: failed to add share %s. Error was %s\n",
00821 sharename, strerror(errno));
00822 talloc_destroy(ctx);
00823 close(tmpfd);
00824 SAFE_FREE(sharename);
00825 return -1;
00826 }
00827
00828 close(tmpfd);
00829 talloc_destroy(ctx);
00830
00831 if (opt_long_list_entries) {
00832 const char *my_argv[2];
00833 my_argv[0] = sharename;
00834 my_argv[1] = NULL;
00835 net_usershare_info(1, my_argv);
00836 }
00837
00838 SAFE_FREE(sharename);
00839 return 0;
00840 }
00841
00842 #if 0
00843
00844
00845
00846
00847 static int list_fn(struct file_list *fl, void *priv)
00848 {
00849 d_printf("%s\n", fl->pathname);
00850 return 0;
00851 }
00852 #endif
00853
00854
00855
00856
00857
00858 static int net_usershare_list(int argc, const char **argv)
00859 {
00860 fstring wcard;
00861 BOOL only_ours = True;
00862 int ret = -1;
00863 struct us_priv_info pi;
00864 TALLOC_CTX *ctx;
00865
00866 fstrcpy(wcard, "*");
00867
00868 if (opt_long_list_entries) {
00869 only_ours = False;
00870 }
00871
00872 switch (argc) {
00873 case 0:
00874 break;
00875 case 1:
00876 fstrcpy(wcard, argv[0]);
00877 break;
00878 default:
00879 return net_usershare_list_usage(argc, argv);
00880 }
00881
00882 strlower_m(wcard);
00883
00884 ctx = talloc_init("share_list");
00885 ret = get_share_list(ctx, wcard, only_ours);
00886 if (ret) {
00887 return ret;
00888 }
00889
00890 pi.ctx = ctx;
00891 pi.op = US_LIST_OP;
00892
00893 ret = process_share_list(info_fn, &pi);
00894 talloc_destroy(ctx);
00895 return ret;
00896 }
00897
00898
00899
00900
00901
00902 int net_usershare_help(int argc, const char **argv)
00903 {
00904 struct functable func[] = {
00905 {"ADD", net_usershare_add_usage},
00906 {"DELETE", net_usershare_delete_usage},
00907 {"INFO", net_usershare_info_usage},
00908 {"LIST", net_usershare_list_usage},
00909 {NULL, NULL}};
00910
00911 return net_run_function(argc, argv, func, net_usershare_usage);
00912 }
00913
00914
00915
00916
00917
00918 int net_usershare(int argc, const char **argv)
00919 {
00920 SMB_STRUCT_DIR *dp;
00921
00922 struct functable func[] = {
00923 {"ADD", net_usershare_add},
00924 {"DELETE", net_usershare_delete},
00925 {"INFO", net_usershare_info},
00926 {"LIST", net_usershare_list},
00927 {"HELP", net_usershare_help},
00928 {NULL, NULL}
00929 };
00930
00931 if (lp_usershare_max_shares() == 0) {
00932 d_fprintf(stderr, "net usershare: usershares are currently disabled\n");
00933 return -1;
00934 }
00935
00936 dp = sys_opendir(lp_usershare_path());
00937 if (!dp) {
00938 int err = errno;
00939 d_fprintf(stderr, "net usershare: cannot open usershare directory %s. Error %s\n",
00940 lp_usershare_path(), strerror(err) );
00941 if (err == EACCES) {
00942 d_fprintf(stderr, "You do not have permission to create a usershare. Ask your "
00943 "administrator to grant you permissions to create a share.\n");
00944 } else if (err == ENOENT) {
00945 d_fprintf(stderr, "Please ask your system administrator to "
00946 "enable user sharing.\n");
00947 }
00948 return -1;
00949 }
00950 sys_closedir(dp);
00951
00952 return net_run_function(argc, argv, func, net_usershare_usage);
00953 }