00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "includes.h"
00023
00024 static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
00025 {
00026 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
00027 if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) {
00028 return FILE_ATTRIBUTE_SPARSE;
00029 }
00030 #endif
00031 return 0;
00032 }
00033
00034
00035
00036
00037
00038 static uint32 set_offline_flag(connection_struct *conn, const char *const path)
00039 {
00040 if (ISDOT(path) || ISDOTDOT(path)) {
00041 return 0;
00042 }
00043
00044 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
00045 return 0;
00046 }
00047
00048 return dmapi_file_flags(path);
00049 }
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname,
00075 const char *inherit_from_dir)
00076 {
00077 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
00078 mode_t dir_mode = 0;
00079
00080
00081 if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) {
00082 result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
00083 }
00084
00085 if (fname && (inherit_from_dir != NULL)
00086 && lp_inherit_perms(SNUM(conn))) {
00087 SMB_STRUCT_STAT sbuf;
00088
00089 DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname,
00090 inherit_from_dir));
00091 if (SMB_VFS_STAT(conn, inherit_from_dir, &sbuf) != 0) {
00092 DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname,
00093 inherit_from_dir, strerror(errno)));
00094 return(0);
00095 }
00096
00097
00098 dir_mode = sbuf.st_mode & ~S_ISUID;
00099 DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode));
00100
00101 result = 0;
00102 }
00103
00104 if (IS_DOS_DIR(dosmode)) {
00105
00106
00107 result |= (S_IFDIR | S_IWUSR);
00108
00109 if (dir_mode) {
00110
00111 result |= dir_mode;
00112 } else {
00113
00114 result |= (S_IXUSR | S_IXGRP | S_IXOTH);
00115
00116
00117 result &= lp_dir_mask(SNUM(conn));
00118
00119 result |= lp_force_dir_mode(SNUM(conn));
00120 }
00121 } else {
00122 if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode))
00123 result |= S_IXUSR;
00124
00125 if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode))
00126 result |= S_IXGRP;
00127
00128 if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode))
00129 result |= S_IXOTH;
00130
00131 if (dir_mode) {
00132
00133 result |= dir_mode & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
00134 } else {
00135
00136 result &= lp_create_mask(SNUM(conn));
00137
00138 result |= lp_force_create_mode(SNUM(conn));
00139 }
00140 }
00141
00142 DEBUG(3,("unix_mode(%s) returning 0%o\n",fname,(int)result ));
00143 return(result);
00144 }
00145
00146
00147
00148
00149
00150 static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
00151 {
00152 int result = 0;
00153 enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn));
00154
00155 if (ro_opts == MAP_READONLY_YES) {
00156
00157 if ((sbuf->st_mode & S_IWUSR) == 0) {
00158 result |= aRONLY;
00159 }
00160 } else if (ro_opts == MAP_READONLY_PERMISSIONS) {
00161
00162 if (!can_write_to_file(conn, path, sbuf)) {
00163 result |= aRONLY;
00164 }
00165 }
00166
00167 if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0))
00168 result |= aARCH;
00169
00170 if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0))
00171 result |= aSYSTEM;
00172
00173 if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0))
00174 result |= aHIDDEN;
00175
00176 if (S_ISDIR(sbuf->st_mode))
00177 result = aDIR | (result & aRONLY);
00178
00179 result |= set_sparse_flag(sbuf);
00180
00181 #ifdef S_ISLNK
00182 #if LINKS_READ_ONLY
00183 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
00184 result |= aRONLY;
00185 #endif
00186 #endif
00187
00188 DEBUG(8,("dos_mode_from_sbuf returning "));
00189
00190 if (result & aHIDDEN) DEBUG(8, ("h"));
00191 if (result & aRONLY ) DEBUG(8, ("r"));
00192 if (result & aSYSTEM) DEBUG(8, ("s"));
00193 if (result & aDIR ) DEBUG(8, ("d"));
00194 if (result & aARCH ) DEBUG(8, ("a"));
00195
00196 DEBUG(8,("\n"));
00197 return result;
00198 }
00199
00200
00201
00202
00203
00204 static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr)
00205 {
00206 ssize_t sizeret;
00207 fstring attrstr;
00208 unsigned int dosattr;
00209
00210 if (!lp_store_dos_attributes(SNUM(conn))) {
00211 return False;
00212 }
00213
00214
00215
00216
00217 sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr));
00218 if (sizeret == -1) {
00219 #if defined(ENOTSUP) && defined(ENOATTR)
00220 if ((errno != ENOTSUP) && (errno != ENOATTR) && (errno != EACCES) && (errno != EPERM)) {
00221 DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
00222 path, strerror(errno) ));
00223 set_store_dos_attributes(SNUM(conn), False);
00224 }
00225 #endif
00226 return False;
00227 }
00228
00229 attrstr[sizeret] = 0;
00230 DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr));
00231
00232 if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' ||
00233 sscanf(attrstr, "%x", &dosattr) != 1) {
00234 DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr));
00235 return False;
00236 }
00237
00238 if (S_ISDIR(sbuf->st_mode)) {
00239 dosattr |= aDIR;
00240 }
00241 *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
00242
00243 DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
00244
00245 if (dosattr & aHIDDEN) DEBUG(8, ("h"));
00246 if (dosattr & aRONLY ) DEBUG(8, ("r"));
00247 if (dosattr & aSYSTEM) DEBUG(8, ("s"));
00248 if (dosattr & aDIR ) DEBUG(8, ("d"));
00249 if (dosattr & aARCH ) DEBUG(8, ("a"));
00250
00251 DEBUG(8,("\n"));
00252
00253 return True;
00254 }
00255
00256
00257
00258
00259
00260 static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
00261 {
00262 fstring attrstr;
00263 files_struct *fsp = NULL;
00264 BOOL ret = False;
00265
00266 if (!lp_store_dos_attributes(SNUM(conn))) {
00267 return False;
00268 }
00269
00270 snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
00271 if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) {
00272 if((errno != EPERM) && (errno != EACCES)) {
00273 if (errno == ENOSYS
00274 #if defined(ENOTSUP)
00275 || errno == ENOTSUP) {
00276 #else
00277 ) {
00278 #endif
00279 set_store_dos_attributes(SNUM(conn), False);
00280 }
00281 return False;
00282 }
00283
00284
00285
00286
00287
00288
00289 if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
00290 return False;
00291
00292
00293
00294
00295
00296
00297
00298 if (!NT_STATUS_IS_OK(open_file_fchmod(conn,path,sbuf,&fsp)))
00299 return ret;
00300 become_root();
00301 if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
00302 ret = True;
00303 }
00304 unbecome_root();
00305 close_file_fchmod(fsp);
00306 return ret;
00307 }
00308 DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path));
00309 return True;
00310 }
00311
00312
00313
00314
00315
00316 uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
00317 {
00318 uint32 result = 0;
00319
00320 DEBUG(8,("dos_mode_msdfs: %s\n", path));
00321
00322 if (!VALID_STAT(*sbuf)) {
00323 return 0;
00324 }
00325
00326
00327
00328 if (lp_hide_dot_files(SNUM(conn))) {
00329 const char *p = strrchr_m(path,'/');
00330 if (p) {
00331 p++;
00332 } else {
00333 p = path;
00334 }
00335
00336 if (p[0] == '.' && p[1] != '.' && p[1] != 0) {
00337 result |= aHIDDEN;
00338 }
00339 }
00340
00341 result |= dos_mode_from_sbuf(conn, path, sbuf);
00342
00343
00344
00345 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
00346 result |= aHIDDEN;
00347 }
00348
00349 DEBUG(8,("dos_mode_msdfs returning "));
00350
00351 if (result & aHIDDEN) DEBUG(8, ("h"));
00352 if (result & aRONLY ) DEBUG(8, ("r"));
00353 if (result & aSYSTEM) DEBUG(8, ("s"));
00354 if (result & aDIR ) DEBUG(8, ("d"));
00355 if (result & aARCH ) DEBUG(8, ("a"));
00356 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
00357
00358 DEBUG(8,("\n"));
00359
00360 return(result);
00361 }
00362
00363
00364
00365
00366
00367 uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
00368 {
00369 uint32 result = 0;
00370
00371 DEBUG(8,("dos_mode: %s\n", path));
00372
00373 if (!VALID_STAT(*sbuf)) {
00374 return 0;
00375 }
00376
00377
00378
00379 if (lp_hide_dot_files(SNUM(conn))) {
00380 const char *p = strrchr_m(path,'/');
00381 if (p) {
00382 p++;
00383 } else {
00384 p = path;
00385 }
00386
00387 if (p[0] == '.' && p[1] != '.' && p[1] != 0) {
00388 result |= aHIDDEN;
00389 }
00390 }
00391
00392
00393 if (get_ea_dos_attribute(conn, path, sbuf, &result)) {
00394 result |= set_sparse_flag(sbuf);
00395 } else {
00396 result |= dos_mode_from_sbuf(conn, path, sbuf);
00397 }
00398
00399 if (S_ISREG(sbuf->st_mode)) {
00400 result |= set_offline_flag(conn, path);
00401 }
00402
00403
00404
00405 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
00406 result |= aHIDDEN;
00407 }
00408
00409 DEBUG(8,("dos_mode returning "));
00410
00411 if (result & aHIDDEN) DEBUG(8, ("h"));
00412 if (result & aRONLY ) DEBUG(8, ("r"));
00413 if (result & aSYSTEM) DEBUG(8, ("s"));
00414 if (result & aDIR ) DEBUG(8, ("d"));
00415 if (result & aARCH ) DEBUG(8, ("a"));
00416 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
00417
00418 DEBUG(8,("\n"));
00419
00420 return(result);
00421 }
00422
00423
00424
00425
00426
00427 int file_set_dosmode(connection_struct *conn, const char *fname,
00428 uint32 dosmode, SMB_STRUCT_STAT *st,
00429 const char *parent_dir)
00430 {
00431 SMB_STRUCT_STAT st1;
00432 int mask=0;
00433 mode_t tmp;
00434 mode_t unixmode;
00435 int ret = -1;
00436
00437
00438 dosmode &= SAMBA_ATTRIBUTES_MASK;
00439
00440 DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
00441
00442 if (st == NULL) {
00443 SET_STAT_INVALID(st1);
00444 st = &st1;
00445 }
00446
00447 if (!VALID_STAT(*st)) {
00448 if (SMB_VFS_STAT(conn,fname,st))
00449 return(-1);
00450 }
00451
00452 unixmode = st->st_mode;
00453
00454 get_acl_group_bits(conn, fname, &st->st_mode);
00455
00456 if (S_ISDIR(st->st_mode))
00457 dosmode |= aDIR;
00458 else
00459 dosmode &= ~aDIR;
00460
00461 if (dos_mode(conn,fname,st) == dosmode) {
00462 st->st_mode = unixmode;
00463 return(0);
00464 }
00465
00466
00467 if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
00468 st->st_mode = unixmode;
00469 return 0;
00470 }
00471
00472 unixmode = unix_mode(conn,dosmode,fname, parent_dir);
00473
00474
00475 mask |= (S_ISUID | S_ISGID);
00476
00477
00478 #ifdef S_ISVTX
00479 mask |= S_ISVTX;
00480 #endif
00481
00482
00483 if (!MAP_ARCHIVE(conn))
00484 mask |= S_IXUSR;
00485 if (!MAP_SYSTEM(conn))
00486 mask |= S_IXGRP;
00487 if (!MAP_HIDDEN(conn))
00488 mask |= S_IXOTH;
00489
00490 unixmode |= (st->st_mode & mask);
00491
00492
00493 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
00494 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
00495 unixmode |= tmp;
00496 }
00497
00498
00499
00500 if (!IS_DOS_READONLY(dosmode)) {
00501 unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
00502 }
00503
00504 if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) {
00505 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
00506 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
00507 st->st_mode = unixmode;
00508 return 0;
00509 }
00510
00511 if((errno != EPERM) && (errno != EACCES))
00512 return -1;
00513
00514 if(!lp_dos_filemode(SNUM(conn)))
00515 return -1;
00516
00517
00518
00519
00520
00521
00522 if (CAN_WRITE(conn)) {
00523
00524
00525
00526
00527
00528
00529
00530
00531 files_struct *fsp;
00532 if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,st,&fsp)))
00533 return -1;
00534 become_root();
00535 ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode);
00536 unbecome_root();
00537 close_file_fchmod(fsp);
00538 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
00539 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
00540 if (ret == 0) {
00541 st->st_mode = unixmode;
00542 }
00543 }
00544
00545 return( ret );
00546 }
00547
00548
00549
00550
00551
00552
00553 int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2])
00554 {
00555 SMB_STRUCT_STAT sbuf;
00556 int ret = -1;
00557
00558 errno = 0;
00559 ZERO_STRUCT(sbuf);
00560
00561
00562
00563
00564
00565
00566
00567
00568 if (!CAN_WRITE(conn)) {
00569 return 0;
00570 }
00571
00572 if(SMB_VFS_NTIMES(conn, fname, ts) == 0) {
00573 return 0;
00574 }
00575
00576 if((errno != EPERM) && (errno != EACCES)) {
00577 return -1;
00578 }
00579
00580 if(!lp_dos_filetimes(SNUM(conn))) {
00581 return -1;
00582 }
00583
00584
00585
00586
00587
00588
00589
00590
00591 if (can_write_to_file(conn, fname, &sbuf)) {
00592
00593 become_root();
00594 ret = SMB_VFS_NTIMES(conn, fname, ts);
00595 unbecome_root();
00596 }
00597
00598 return ret;
00599 }
00600
00601
00602
00603
00604
00605 BOOL set_filetime(connection_struct *conn, const char *fname,
00606 const struct timespec mtime)
00607 {
00608 struct timespec ts[2];
00609
00610 if (null_timespec(mtime)) {
00611 return(True);
00612 }
00613
00614 ts[1] = mtime;
00615 ts[0] = ts[1];
00616
00617 if (file_ntimes(conn, fname, ts)) {
00618 DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
00619 return False;
00620 }
00621
00622 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
00623 FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
00624
00625 return True;
00626 }