chmod.cpp
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:9k
源码类别:

Ftp客户端

开发平台:

Visual C++

  1. // This is part of the WAR SOFTWARE SERIES initiated by Jarle Aase
  2. // Copyright 1996 by Jarle Aase. All rights reserved.
  3. // See the "War Software Series Licende Agreement" for details concerning 
  4. // use and distribution.
  5. // ---
  6. // This source code, executables and programs containing source code or
  7. // binaries or proprietetary technology from the War Software Series are
  8. // NOT alloed used, viewed or tested by any governmental agencies in
  9. // any countries. This includes the government, departments, police, 
  10. // military etc.
  11. // ---
  12. // This file is intended for use with Tab space = 2
  13. // Created and maintained in MSVC Developer Studio
  14. // ---
  15. // NAME : chmod.cpp
  16. // PURPOSE : extended UNIX chmod command
  17. // PROGRAM : 
  18. // DATE : Oct. 13 1996
  19. // AUTHOR : Jarle Aase
  20. // ---
  21. // REVISION HISTORY
  22. // 
  23. #include "stdafx.h"
  24. // For now, we don't support non-daemon programs
  25. //#include "WarSoftware.h"
  26. #include "WarDaemon.h"
  27. #include "WarFsys.h"
  28. #include "VfFSys.h"
  29. #include "UnixFsysTypes.h"
  30. #ifdef _DEBUG
  31. #define new DEBUG_NEW
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. CChmod::CChmod(CFsysThread *pFsysThread)
  36. {
  37. set = NULL;
  38. m_Owner = -1;
  39. m_Group = -1;
  40. m_Comment = NULL;
  41. m_DefDirPerms = -1;
  42. m_DefFilePerms = -1;
  43. omode = -1;
  44. m_SetMode = FALSE;
  45. m_pFsysThread = pFsysThread;
  46. m_SpecialNewFilePerm = -1;
  47. }
  48. CChmod::~CChmod()
  49. {
  50. if (set)
  51. free(set);
  52. }
  53. int CChmod::main(int argc, char **argv)
  54. {
  55. char *ep, *mode;
  56. BOOL Alternate = FALSE;
  57. CFileList MasterFileList;
  58. int Rval;
  59. set = NULL;
  60. omode = 0;
  61. Hflag = Lflag = Pflag = Rflag = fflag = hflag = 0;
  62. while ((ch = getopt(argc, argv, "N:O:G:C:D:F:HLPRXfgorstuwx")) != EOF)
  63. switch (ch) 
  64. {
  65. case 'N': // SpecialNewFilePerm (octal)
  66. if (!optarg || !*optarg)
  67. goto badarg;
  68. sscanf(optarg,"%o", &m_SpecialNewFilePerm);
  69. Alternate = TRUE;
  70. break;
  71. case 'O': // chown
  72. if (!optarg || !*optarg)
  73. goto badarg;
  74. if (atoi(optarg))
  75. m_Owner = atoi(optarg);
  76. else if ((m_Owner = CUsr::FindUser(UT_USER, optarg)) == 0)
  77. {
  78. printf("Unknown user name '%s'n", optarg);
  79. return -1;
  80. }
  81. Alternate = TRUE;
  82. break;
  83. case 'G': // chown
  84. if (!optarg || !*optarg)
  85. goto badarg;
  86. if (!optarg || !*optarg)
  87. goto badarg;
  88. if (atoi(optarg))
  89. m_Group = atoi(optarg);
  90. else if ((m_Group = CUsr::FindUser(UT_CLASS, optarg)) == 0)
  91. {
  92. printf("Unknown class name '%s'n", optarg);
  93. return -1;
  94. }
  95. Alternate = TRUE;
  96. break;
  97. case 'C': // change comment
  98. if (!optarg)
  99. goto badarg;
  100. m_Comment = optarg;
  101. Alternate = TRUE;
  102. break;
  103. case 'D':
  104. if (!optarg || !*optarg || (*optarg < '0') || (*optarg > '8'))
  105. goto badarg;
  106. m_DefDirPerms = strtol(optarg, &ep, 8);
  107. Alternate = TRUE;
  108. break;
  109. case 'F':
  110. if (!optarg || !*optarg || (*optarg < '0') || (*optarg > '8'))
  111. goto badarg;
  112. m_DefFilePerms = strtol(optarg, &ep, 8);
  113. Alternate = TRUE;
  114. break;
  115. case 'H':
  116. Hflag = 1;
  117. Lflag = Pflag = 0;
  118. break;
  119. case 'L':
  120. Lflag = 1;
  121. Hflag = Pflag = 0;
  122. break;
  123. case 'P':
  124. Pflag = 1;
  125. Hflag = Lflag = 0;
  126. break;
  127. case 'R':
  128. Rflag = 1;
  129. break;
  130. case 'f': /* XXX: undocumented. */
  131. fflag = 1;
  132. break;
  133. case 'h':
  134. /*
  135.  * In System V (and probably POSIX.2) the -h option
  136.  * causes chmod to change the mode of the symbolic
  137.  * link.  4.4BSD's symbolic links don't have modes,
  138.  * so it's an undocumented noop.  Do syntax checking,
  139.  * though.
  140.  */
  141. hflag = 1;
  142. break;
  143. /*
  144.  * XXX
  145.  * "-[rwx]" are valid mode commands.  If they are the entire
  146.  * argument, getopt has moved past them, so decrement optind.
  147.  * Regardless, we're done argument processing.
  148.  */
  149. case 'g': case 'o': case 'r': case 's':
  150. case 't': case 'u': case 'w': case 'X': case 'x':
  151. if (argv[optind - 1][0] == '-' &&
  152.     argv[optind - 1][1] == ch &&
  153.     argv[optind - 1][2] == '')
  154. --optind;
  155. Alternate = FALSE;
  156. goto done;
  157. case '?':
  158. default:
  159. return usage();
  160. }
  161. done:
  162. argv += optind;
  163. argc -= optind;
  164. if (Rflag) 
  165. {
  166. if (hflag)
  167. {
  168. printf("the -R and -h options may not be specified together.");
  169. return usage();
  170. }
  171. }
  172. if (!Alternate)
  173. {
  174. if (argc < 2)
  175. return usage();
  176. m_SetMode = TRUE;
  177. mode = *argv;
  178. --argc;
  179. ++argv;
  180. if (*mode >= '0' && *mode <= '7') 
  181. {
  182. val = strtol(mode, &ep, 8);
  183. if (val > INT_MAX || val < 0)
  184. {
  185. printf("invalid file mode: %s", mode);
  186. return 1;
  187. }
  188. if (*ep)
  189. {
  190. printf("invalid file mode: %s", mode);
  191. return 1;
  192. }
  193. omode = val;
  194. oct = 1;
  195. else 
  196. {
  197. if ((set = setmode(mode)) == NULL)
  198. {
  199. printf("invalid file mode: %s", mode);
  200. return 1;
  201. }
  202. oct = 0;
  203. }
  204. }
  205. pLock->WriteLock();
  206. Rval = Process(argc, argv, 0, MasterFileList);
  207. pLock->UnlockWrite();
  208. return Rval;
  209. badarg:
  210. return usage();
  211. }
  212. int CChmod::Process(int argc, char **argv, int Level, CFileList& MasterFileList)
  213. {
  214. int argcSave = argc;
  215. char **argvSave = argv;
  216. for(;argc ; argc--, argv++)
  217. {
  218. // Prepere file system
  219. CString Path = *argv;
  220. m_pFsysThread->ParsePath(Path);
  221. m_pFsysThread->ScanPath(Path, FALSE, Rflag, FALSE, FALSE);
  222. }
  223. int Rval = _Process(argcSave, argvSave, Level, MasterFileList);
  224. return Rval;
  225. }
  226. int CChmod::_Process(int argc, char **argv, int Level, CFileList& MasterFileList)
  227. {
  228. CString cShowPath, cCurrentPath;
  229. CLinkedListItem *Item;
  230. ASSERT(argc >= 1);
  231. for(;argc ; argc--, argv++)
  232. {
  233. CFileList FileList;
  234. ASSERT(AfxIsValidString(*argv));
  235. if (m_VisitedDirs.Find(*argv))
  236. continue; // Already been here
  237. cCurrentPath = cShowPath = *argv;
  238. m_pFsysThread->BldFileInfoList(FileList, *argv, Rflag);
  239. if (Rflag)
  240. {
  241. m_VisitedDirs.AddHead(*argv);
  242. int Rval;
  243. for(Item = FileList.First(); Item; Item = FileList.Next(Item))
  244. {
  245. FILE_NODE *pNode = (FILE_NODE *)FileList.Ptr(Item);
  246. if ((pNode->Perms & NODE_DIR) 
  247. && strcmp(pNode->Name,".") && strcmp(pNode->Name,".."))
  248. {
  249. CString cBuf;
  250. // We need to modify the current path
  251. LPSTR p = cCurrentPath.GetBuffer(1);
  252. LPSTR pp = strrchr(p, '/');
  253. if (pp)
  254. *pp = 0;
  255. else
  256. *p = 0;
  257. cCurrentPath.ReleaseBuffer();
  258. if (cCurrentPath.IsEmpty())
  259. cBuf = pNode->Name;
  260. else
  261. cBuf.Format("%s/%s", cCurrentPath, pNode->Name);
  262. cBuf += "/*";
  263. LPSTR MyArgs[1];
  264. MyArgs[0] = cBuf.GetBuffer(1);
  265. if (Rval = Process(1, MyArgs, Level +1, MasterFileList))
  266. return Rval; // Error
  267. }
  268. }
  269. }
  270. MasterFileList += FileList;
  271. }
  272. if (!Level)
  273. {
  274. if (!ChmodFileList(MasterFileList, cShowPath))
  275. return -1;
  276. // Flush
  277. for(Item = MasterFileList.First(); Item; Item = MasterFileList.Next(Item))
  278. {
  279. FILE_NODE *pNode = (FILE_NODE *)MasterFileList.Ptr(Item);
  280. m_pFsysThread->Flush(pNode->Father);
  281. }
  282. }
  283. return 0;
  284. }
  285. BOOL CChmod::ChmodFileList(CFileList& FileList, LPCSTR Path)
  286. {
  287. FILE_NODE *pNode;
  288. LPCSTR FileName;
  289. CLinkedListItem *Item;
  290. for(Item = FileList.First(); Item; Item = FileList.Next(Item))
  291. {
  292. pNode = (FILE_NODE *)FileList.Ptr(Item);
  293. FileName = pNode->Name;
  294. ASSERT(AfxIsValidString(FileName));
  295. if (!strcmp(FileName,".") || !strcmp(FileName,".."))
  296. continue;
  297. // Change the mode
  298. if (__chmod(
  299. pNode, 
  300. m_SetMode ? oct ? omode : getmode(set,pNode->Perms) : -1,
  301. m_Owner, m_Group, m_Comment, m_DefDirPerms, m_DefFilePerms, m_SpecialNewFilePerm))
  302. {
  303. printf("chmod: %s - mode change failed %s/%sn", Path, FileName, GetLastErrorText());
  304. }
  305. }
  306. return TRUE;
  307. }
  308. int CChmod::usage()
  309. {
  310. printf("usage: chmod [-R [-H | -L | -P]] mode file ...n");
  311. printf("  or   chmod [-O Owner] [-G Class] [-C "Comment"] [-D DefDirPerms] [-F DefFilePerms] file ...n");
  312. printf("  or   chmod -N SpecialNewFilePerms directory ... (value is octal, default is 022)n");
  313. return 1;
  314. }
  315. // Chmod on a single file
  316. // Return 0 on success
  317. int CChmod::__chmod(FILE_NODE *pNode, int SetMode, int SetOwner, 
  318. int SetClass, LPCSTR SetComment, int DefDirMode, int DefFileMode,
  319. int SpecialNewFilePerm)
  320. {
  321. int rval = 0;
  322. DWORD PreserveFlags = pNode->Perms & ~NODE_SETTABLE;
  323. // Check permission
  324. if (!m_Fsys->m_IsAdmin && (m_Fsys->m_User != pNode->User))
  325. {
  326. SetLastError(ERROR_ACCESS_DENIED);
  327. return -1;
  328. }
  329. // Set the new permissions
  330. if (SetMode != -1)
  331. pNode->Perms = (SetMode & NODE_SETTABLE) | PreserveFlags;
  332. if (SetOwner != -1)
  333. pNode->User = SetOwner;
  334. if (SetClass != -1)
  335. pNode->Class = SetClass;
  336. if ((SpecialNewFilePerm != -1) && (pNode->Perms & NODE_DIR))
  337. ((DIR_NODE *)pNode)->SpecialNewFilePerm = SpecialNewFilePerm;
  338. if (SetComment)
  339. ChangeNodeInformation(pNode, NULL, NULL, NULL, SetComment);
  340. DIR_NODE *pDir = (DIR_NODE *)pSmem->__Ptr(pNode->Father);
  341. if (pDir)
  342. pDir->f_Dirty = TRUE;
  343. return 0;
  344. }