• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "errno.h"
33 #include "stdlib.h"
34 #include "string.h"
35 #include "dirent.h"
36 #include "unistd.h"
37 #include "sys/select.h"
38 #include "sys/mount.h"
39 #include "sys/stat.h"
40 #include "sys/statfs.h"
41 #include "sys/prctl.h"
42 #include "fs/fd_table.h"
43 #include "fs/file.h"
44 #include "linux/spinlock.h"
45 #include "los_process_pri.h"
46 #include "los_task_pri.h"
47 #include "capability_api.h"
48 #include "vnode.h"
49 
50 #define MAX_DIR_ENT 1024
fstat(int fd,struct stat * buf)51 int fstat(int fd, struct stat *buf)
52 {
53     struct file *filep = NULL;
54 
55     int ret = fs_getfilep(fd, &filep);
56     if (ret < 0) {
57         return VFS_ERROR;
58     }
59 
60     return stat(filep->f_path, buf);
61 }
62 
fstat64(int fd,struct stat64 * buf)63 int fstat64(int fd, struct stat64 *buf)
64 {
65     struct file *filep = NULL;
66 
67     int ret = fs_getfilep(fd, &filep);
68     if (ret < 0) {
69         return VFS_ERROR;
70     }
71 
72     return stat64(filep->f_path, buf);
73 }
74 
lstat(const char * path,struct stat * buffer)75 int lstat(const char *path, struct stat *buffer)
76 {
77     return stat(path, buffer);
78 }
79 
VfsVnodePermissionCheck(const struct Vnode * node,int accMode)80 int VfsVnodePermissionCheck(const struct Vnode *node, int accMode)
81 {
82     uint fuid = node->uid;
83     uint fgid = node->gid;
84     uint fileMode = node->mode;
85     return VfsPermissionCheck(fuid, fgid, fileMode, accMode);
86 }
87 
VfsPermissionCheck(uint fuid,uint fgid,uint fileMode,int accMode)88 int VfsPermissionCheck(uint fuid, uint fgid, uint fileMode, int accMode)
89 {
90     uint uid = OsCurrUserGet()->effUserID;
91     mode_t tmpMode = fileMode;
92 
93     if (uid == fuid) {
94         tmpMode >>= USER_MODE_SHIFT;
95     } else if (LOS_CheckInGroups(fgid)) {
96         tmpMode >>= GROUP_MODE_SHIFT;
97     }
98 
99     tmpMode &= (READ_OP | WRITE_OP | EXEC_OP);
100 
101     if (((uint)accMode & tmpMode) == accMode) {
102         return 0;
103     }
104 
105     tmpMode = 0;
106     if (S_ISDIR(fileMode)) {
107         if (IsCapPermit(CAP_DAC_EXECUTE)
108             || (!((uint)accMode & WRITE_OP) && IsCapPermit(CAP_DAC_READ_SEARCH))) {
109             tmpMode |= EXEC_OP;
110         }
111     } else {
112         if (IsCapPermit(CAP_DAC_EXECUTE) && (fileMode & MODE_IXUGO)) {
113             tmpMode |= EXEC_OP;
114         }
115     }
116 
117     if (IsCapPermit(CAP_DAC_WRITE)) {
118         tmpMode |= WRITE_OP;
119     }
120 
121     if (IsCapPermit(CAP_DAC_READ_SEARCH)) {
122         tmpMode |= READ_OP;
123     }
124 
125     if (((uint)accMode & tmpMode) == accMode) {
126         return 0;
127     }
128 
129     return 1;
130 }
131 
132 #ifdef VFS_USING_WORKDIR
SetWorkDir(const char * dir,size_t len)133 static int SetWorkDir(const char *dir, size_t len)
134 {
135     errno_t ret;
136     uint lock_flags;
137     LosProcessCB *curr = OsCurrProcessGet();
138 
139     spin_lock_irqsave(&curr->files->workdir_lock, lock_flags);
140     ret = strncpy_s(curr->files->workdir, PATH_MAX, dir, len);
141     curr->files->workdir[PATH_MAX - 1] = '\0';
142     spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
143     if (ret != EOK) {
144         return -1;
145     }
146 
147         return 0;
148 }
149 #endif
150 
chdir(const char * path)151 int chdir(const char *path)
152 {
153     int ret;
154     char *fullpath = NULL;
155     char *fullpath_bak = NULL;
156     struct stat statBuff;
157 
158     if (!path) {
159         set_errno(EFAULT);
160         return -1;
161     }
162 
163     if (!strlen(path)) {
164         set_errno(ENOENT);
165         return -1;
166     }
167 
168     if (strlen(path) > PATH_MAX) {
169         set_errno(ENAMETOOLONG);
170         return -1;
171     }
172 
173     ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
174     if (ret < 0) {
175         set_errno(-ret);
176         return -1; /* build path failed */
177     }
178     fullpath_bak = fullpath;
179     ret = stat(fullpath, &statBuff);
180     if (ret < 0) {
181         free(fullpath_bak);
182         return -1;
183     }
184 
185     if (!S_ISDIR(statBuff.st_mode)) {
186         set_errno(ENOTDIR);
187         free(fullpath_bak);
188         return -1;
189     }
190 
191     if (VfsPermissionCheck(statBuff.st_uid, statBuff.st_gid, statBuff.st_mode, EXEC_OP)) {
192         set_errno(EACCES);
193         free(fullpath_bak);
194         return -1;
195     }
196 
197 #ifdef VFS_USING_WORKDIR
198     ret = SetWorkDir(fullpath, strlen(fullpath));
199     if (ret != 0) {
200         PRINT_ERR("chdir path error!\n");
201         ret = -1;
202     }
203 #endif
204 
205     /* release normalize directory path name */
206 
207     free(fullpath_bak);
208 
209     return ret;
210 }
211 
212 /**
213  * this function is a POSIX compliant version, which will return current
214  * working directory.
215  *
216  * @param buf the returned current directory.
217  * @param size the buffer size.
218  *
219  * @return the returned current directory.
220  */
221 
getcwd(char * buf,size_t n)222 char *getcwd(char *buf, size_t n)
223 {
224 #ifdef VFS_USING_WORKDIR
225     int ret;
226     unsigned int len;
227     UINTPTR lock_flags;
228     LosProcessCB *curr = OsCurrProcessGet();
229 #endif
230     if (buf == NULL) {
231         set_errno(EINVAL);
232         return buf;
233     }
234 #ifdef VFS_USING_WORKDIR
235     spin_lock_irqsave(&curr->files->workdir_lock, lock_flags);
236     len = strlen(curr->files->workdir);
237     if (n <= len) {
238         set_errno(ERANGE);
239         spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
240         return NULL;
241     }
242     ret = memcpy_s(buf, n, curr->files->workdir, len + 1);
243     if (ret != EOK) {
244         set_errno(ENAMETOOLONG);
245         spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
246         return NULL;
247     }
248     spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
249 #else
250     PRINT_ERR("NO_WORKING_DIR\n");
251 #endif
252 
253     return buf;
254 }
255 
chmod(const char * path,mode_t mode)256 int chmod(const char *path, mode_t mode)
257 {
258     struct IATTR attr = {0};
259     attr.attr_chg_mode = mode;
260     attr.attr_chg_valid = CHG_MODE; /* change mode */
261     int ret;
262 
263     ret = chattr(path, &attr);
264     if (ret < 0) {
265         return VFS_ERROR;
266     }
267 
268     return OK;
269 }
270 
chown(const char * pathname,uid_t owner,gid_t group)271 int chown(const char *pathname, uid_t owner, gid_t group)
272 {
273     struct IATTR attr = {0};
274     attr.attr_chg_valid = 0;
275     int ret;
276 
277     if (owner != (uid_t)-1) {
278         attr.attr_chg_uid = owner;
279         attr.attr_chg_valid |= CHG_UID;
280     }
281     if (group != (gid_t)-1) {
282         attr.attr_chg_gid = group;
283         attr.attr_chg_valid |= CHG_GID;
284     }
285     ret = chattr(pathname, &attr);
286     if (ret < 0) {
287         return VFS_ERROR;
288     }
289 
290     return OK;
291 }
292 
access(const char * path,int amode)293 int access(const char *path, int amode)
294 {
295     int ret;
296     struct stat buf;
297     struct statfs fsBuf;
298 
299     ret = statfs(path, &fsBuf);
300     if (ret != 0) {
301         if (get_errno() != ENOSYS) {
302             return VFS_ERROR;
303         }
304         /* dev has no statfs ops, need devfs to handle this in feature */
305     }
306 
307     if ((fsBuf.f_flags & MS_RDONLY) && ((unsigned int)amode & W_OK)) {
308         set_errno(EROFS);
309         return VFS_ERROR;
310     }
311 
312     ret = stat(path, &buf);
313     if (ret != 0) {
314         return VFS_ERROR;
315     }
316 
317     if (VfsPermissionCheck(buf.st_uid, buf.st_gid, buf.st_mode, amode)) {
318         set_errno(EACCES);
319         return VFS_ERROR;
320     }
321 
322     return OK;
323 }
324 
scandir_get_file_list(const char * dir,int * num,int (* filter)(const struct dirent *))325 static struct dirent **scandir_get_file_list(const char *dir, int *num, int(*filter)(const struct dirent *))
326 {
327     DIR *od = NULL;
328     int listSize = MAX_DIR_ENT;
329     int n = 0;
330     struct dirent **list = NULL;
331     struct dirent **newList = NULL;
332     struct dirent *ent = NULL;
333     struct dirent *p = NULL;
334     int err;
335 
336     od = opendir(dir);
337     if (od == NULL) {
338         return NULL;
339     }
340 
341     list = (struct dirent **)malloc(listSize * sizeof(struct dirent *));
342     if (list == NULL) {
343         (void)closedir(od);
344         return NULL;
345     }
346 
347     for (ent = readdir(od); ent != NULL; ent = readdir(od)) {
348         if (filter && !filter(ent)) {
349             continue;
350         }
351 
352         if (n == listSize) {
353             listSize += MAX_DIR_ENT;
354             newList = (struct dirent **)malloc(listSize * sizeof(struct dirent *));
355             if (newList == NULL) {
356                 break;
357             }
358 
359             err = memcpy_s(newList, listSize * sizeof(struct dirent *), list, n * sizeof(struct dirent *));
360             if (err != EOK) {
361                 free(newList);
362                 break;
363             }
364             free(list);
365             list = newList;
366         }
367 
368         p = (struct dirent *)malloc(sizeof(struct dirent));
369         if (p == NULL) {
370             break;
371         }
372 
373         (void)memcpy_s((void *)p, sizeof(struct dirent), (void *)ent, sizeof(struct dirent));
374         list[n] = p;
375 
376         n++;
377     }
378 
379     if (closedir(od) < 0) {
380         while (n--) {
381             free(list[n]);
382         }
383         free(list);
384         return NULL;
385     }
386 
387     *num = n;
388     return list;
389 }
390 
scandir(const char * dir,struct dirent *** namelist,int (* filter)(const struct dirent *),int (* compar)(const struct dirent **,const struct dirent **))391 int scandir(const char *dir, struct dirent ***namelist,
392             int(*filter)(const struct dirent *),
393             int(*compar)(const struct dirent **, const struct dirent **))
394 {
395     int n = 0;
396     struct dirent **list = NULL;
397 
398     if ((dir == NULL) || (namelist == NULL)) {
399         return -1;
400     }
401 
402     list = scandir_get_file_list(dir, &n, filter);
403     if (list == NULL) {
404         return -1;
405     }
406 
407     /* Change to return to the array size */
408     *namelist = (struct dirent **)malloc(n * sizeof(struct dirent *));
409     if (*namelist == NULL && n > 0) {
410         *namelist = list;
411     } else if (*namelist != NULL) {
412         (void)memcpy_s(*namelist, n * sizeof(struct dirent *), list, n * sizeof(struct dirent *));
413         free(list);
414     } else {
415         free(list);
416     }
417 
418     /* Sort array */
419 
420     if (compar && *namelist) {
421         qsort((void *)*namelist, (size_t)n, sizeof(struct dirent *), (int (*)(const void *, const void *))*compar);
422     }
423 
424     return n;
425 }
426 
alphasort(const struct dirent ** a,const struct dirent ** b)427 int alphasort(const struct dirent **a, const struct dirent **b)
428 {
429     return strcoll((*a)->d_name, (*b)->d_name);
430 }
431 
rindex(const char * s,int c)432 char *rindex(const char *s, int c)
433 {
434     if (s == NULL) {
435         return NULL;
436     }
437 
438     /* Don't bother tracing - strrchr can do that */
439     return (char *)strrchr(s, c);
440 }
441 
ls_get_fullpath(const char * path,struct dirent * pdirent)442 static char *ls_get_fullpath(const char *path, struct dirent *pdirent)
443 {
444     char *fullpath = NULL;
445     int ret;
446 
447     if (path[1] != '\0') {
448         /* 2, The position of the path character: / and the end character '/0' */
449         fullpath = (char *)malloc(strlen(path) + strlen(pdirent->d_name) + 2);
450         if (fullpath == NULL) {
451             goto exit_with_nomem;
452         }
453 
454         /* 2, The position of the path character: / and the end character '/0' */
455         ret = snprintf_s(fullpath, strlen(path) + strlen(pdirent->d_name) + 2,
456                          strlen(path) + strlen(pdirent->d_name) + 1, "%s/%s", path, pdirent->d_name);
457         if (ret < 0) {
458             free(fullpath);
459             set_errno(ENAMETOOLONG);
460             return NULL;
461         }
462     } else {
463         /* 2, The position of the path character: / and the end character '/0' */
464         fullpath = (char *)malloc(strlen(pdirent->d_name) + 2);
465         if (fullpath == NULL) {
466             goto exit_with_nomem;
467         }
468 
469         /* 2, The position of the path character: / and the end character '/0' */
470         ret = snprintf_s(fullpath, strlen(pdirent->d_name) + 2, strlen(pdirent->d_name) + 1,
471                          "/%s", pdirent->d_name);
472         if (ret < 0) {
473             free(fullpath);
474             set_errno(ENAMETOOLONG);
475             return NULL;
476         }
477     }
478     return fullpath;
479 
480 exit_with_nomem:
481     set_errno(ENOSPC);
482     return (char *)NULL;
483 }
484 
PrintFileInfo64(const struct stat64 * stat64Info,const char * name)485 static void PrintFileInfo64(const struct stat64 *stat64Info, const char *name)
486 {
487     mode_t mode;
488     char str[UGO_NUMS][UGO_NUMS + 1] = {0};
489     char dirFlag;
490     int i;
491 
492     for (i = 0; i < UGO_NUMS; i++) {
493         mode = stat64Info->st_mode >> (uint)(USER_MODE_SHIFT - i * UGO_NUMS);
494         str[i][0] = (mode & READ_OP) ? 'r' : '-';
495         str[i][1] = (mode & WRITE_OP) ? 'w' : '-';
496         str[i][UGO_NUMS - 1] = (mode & EXEC_OP) ? 'x' : '-';
497     }
498 
499     if (S_ISDIR(stat64Info->st_mode)) {
500         dirFlag = 'd';
501     } else if (S_ISLNK(stat64Info->st_mode)) {
502         dirFlag = 'l';
503     } else {
504         dirFlag = '-';
505     }
506 
507     PRINTK("%c%s%s%s %-8lld u:%-5d g:%-5d %-10s\n", dirFlag,
508            str[0], str[1], str[UGO_NUMS - 1], stat64Info->st_size, stat64Info->st_uid, stat64Info->st_gid, name);
509 }
510 
PrintFileInfo(const struct stat * statInfo,const char * name)511 static void PrintFileInfo(const struct stat *statInfo, const char *name)
512 {
513     mode_t mode;
514     char str[UGO_NUMS][UGO_NUMS + 1] = {0};
515     char dirFlag;
516     int i;
517 
518     for (i = 0; i < UGO_NUMS; i++) {
519         mode = statInfo->st_mode >> (uint)(USER_MODE_SHIFT - i * UGO_NUMS);
520         str[i][0] = (mode & READ_OP) ? 'r' : '-';
521         str[i][1] = (mode & WRITE_OP) ? 'w' : '-';
522         str[i][UGO_NUMS - 1] = (mode & EXEC_OP) ? 'x' : '-';
523     }
524 
525     if (S_ISDIR(statInfo->st_mode)) {
526         dirFlag = 'd';
527     } else if (S_ISLNK(statInfo->st_mode)) {
528         dirFlag = 'l';
529     } else {
530         dirFlag = '-';
531     }
532 
533     PRINTK("%c%s%s%s %-8lld u:%-5d g:%-5d %-10s\n", dirFlag,
534            str[0], str[1], str[UGO_NUMS - 1], statInfo->st_size, statInfo->st_uid, statInfo->st_gid, name);
535 }
536 
LsFile(const char * path)537 int LsFile(const char *path)
538 {
539     struct stat64 stat64Info;
540     struct stat statInfo;
541 
542     if (stat64(path, &stat64Info) == 0) {
543         PrintFileInfo64(&stat64Info, path);
544     } else if (stat(path, &statInfo) == 0) {
545         PrintFileInfo(&statInfo, path);
546     } else {
547         return -1;
548     }
549 
550     return 0;
551 }
552 
LsDir(const char * path)553 int LsDir(const char *path)
554 {
555     struct stat statInfo = { 0 };
556     struct stat64 stat64Info = { 0 };
557     DIR *d = NULL;
558     char *fullpath = NULL;
559     char *fullpath_bak = NULL;
560     struct dirent *pdirent = NULL;
561 
562     d = opendir(path);
563     if (d == NULL) {
564         return -1;
565     }
566 
567     PRINTK("Directory %s:\n", path);
568     do {
569         pdirent = readdir(d);
570         if (pdirent == NULL) {
571             break;
572         } else {
573             if (!strcmp(pdirent->d_name, ".") || !strcmp(pdirent->d_name, "..")) {
574                 continue;
575             }
576             (void)memset_s(&statInfo, sizeof(struct stat), 0, sizeof(struct stat));
577             (void)memset_s(&stat64Info, sizeof(struct stat), 0, sizeof(struct stat));
578             fullpath = ls_get_fullpath(path, pdirent);
579             if (fullpath == NULL) {
580                 (void)closedir(d);
581                 return -1;
582             }
583 
584             fullpath_bak = fullpath;
585             if (stat64(fullpath, &stat64Info) == 0) {
586                 PrintFileInfo64(&stat64Info, pdirent->d_name);
587             } else if (stat(fullpath, &statInfo) == 0) {
588                 PrintFileInfo(&statInfo, pdirent->d_name);
589             } else {
590                 PRINTK("BAD file: %s\n", pdirent->d_name);
591             }
592             free(fullpath_bak);
593         }
594     } while (1);
595     (void)closedir(d);
596 
597     return 0;
598 }
599 
ls(const char * pathname)600 void ls(const char *pathname)
601 {
602     struct stat statInfo = { 0 };
603     char *path = NULL;
604     int ret;
605 
606     if (pathname == NULL) {
607 #ifdef VFS_USING_WORKDIR
608         UINTPTR lock_flags;
609         LosProcessCB *curr = OsCurrProcessGet();
610 
611         /* open current working directory */
612 
613         spin_lock_irqsave(&curr->files->workdir_lock, lock_flags);
614         path = strdup(curr->files->workdir);
615         spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
616 #else
617         path = strdup("/");
618 #endif
619         if (path == NULL) {
620             return;
621         }
622     } else {
623         ret = vfs_normalize_path(NULL, pathname, &path);
624         if (ret < 0) {
625             set_errno(-ret);
626             return;
627         }
628     }
629 
630     ret = stat(path, &statInfo);
631     if (ret < 0) {
632         perror("ls error");
633         free(path);
634         return;
635     }
636 
637     if (statInfo.st_mode & S_IFDIR) { /* list all directory and file */
638         ret = LsDir((pathname == NULL) ? path : pathname);
639     } else { /* show the file information */
640         ret = LsFile(path);
641     }
642     if (ret < 0) {
643         perror("ls error");
644     }
645 
646     free(path);
647     return;
648 }
649 
650 
realpath(const char * path,char * resolved_path)651 char *realpath(const char *path, char *resolved_path)
652 {
653     int ret, result;
654     char *new_path = NULL;
655     struct stat buf;
656 
657     ret = vfs_normalize_path(NULL, path, &new_path);
658     if (ret < 0) {
659         ret = -ret;
660         set_errno(ret);
661         return NULL;
662     }
663 
664     result = stat(new_path, &buf);
665 
666     if (resolved_path == NULL) {
667         if (result != ENOERR) {
668             free(new_path);
669             return NULL;
670         }
671         return new_path;
672     }
673 
674     ret = strcpy_s(resolved_path, PATH_MAX, new_path);
675     if (ret != EOK) {
676         ret = -ret;
677         set_errno(ret);
678         free(new_path);
679         return NULL;
680     }
681 
682     free(new_path);
683     if (result != ENOERR) {
684         return NULL;
685     }
686     return resolved_path;
687 }
688 
lsfd(void)689 void lsfd(void)
690 {
691     struct filelist *f_list = NULL;
692     unsigned int i = 3; /* file start fd */
693     int ret;
694     struct Vnode *node = NULL;
695 
696     f_list = &tg_filelist;
697 
698     PRINTK("   fd    filename\n");
699     ret = sem_wait(&f_list->fl_sem);
700     if (ret < 0) {
701         PRINTK("sem_wait error, ret=%d\n", ret);
702         return;
703     }
704 
705     while (i < CONFIG_NFILE_DESCRIPTORS) {
706         node = files_get_openfile(i);
707         if (node) {
708             PRINTK("%5d   %s\n", i, f_list->fl_files[i].f_path);
709         }
710         i++;
711     }
712     (void)sem_post(&f_list->fl_sem);
713 }
714 
GetUmask(void)715 mode_t GetUmask(void)
716 {
717     return OsCurrProcessGet()->umask;
718 }
719 
SysUmask(mode_t mask)720 mode_t SysUmask(mode_t mask)
721 {
722     UINT32 intSave;
723     mode_t umask;
724     mode_t oldUmask;
725     umask = mask & UMASK_FULL;
726     SCHEDULER_LOCK(intSave);
727     oldUmask = OsCurrProcessGet()->umask;
728     OsCurrProcessGet()->umask = umask;
729     SCHEDULER_UNLOCK(intSave);
730     return oldUmask;
731 }
732 
733