Path openat
Retired DISLab
http://lxr.free-electrons.com/source/fs/namei.c#L3152
3152 static struct file *path_openat(int dfd, struct filename *pathname, 3153 struct nameidata *nd, const struct open_flags *op, int flags) 3154 { 3155 struct file *base = NULL; 3156 struct file *file; 3157 struct path path; 3158 int opened = 0; 3159 int error; 3160 3161 file = get_empty_filp(); 3162 if (IS_ERR(file)) 3163 return file; 3164 3165 file->f_flags = op->open_flag; 3166 3167 if (unlikely(file->f_flags & __O_TMPFILE)) { 3168 error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened); 3169 goto out; 3170 } 3171 3172 error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base); 3173 if (unlikely(error)) 3174 goto out; 3175 3176 current->total_link_count = 0; 3177 error = link_path_walk(pathname->name, nd); 3178 if (unlikely(error)) 3179 goto out; 3180 3181 error = do_last(nd, &path, file, op, &opened, pathname); 3182 while (unlikely(error > 0)) { /* trailing symlink */ 3183 struct path link = path; 3184 void *cookie; 3185 if (!(nd->flags & LOOKUP_FOLLOW)) { 3186 path_put_conditional(&path, nd); 3187 path_put(&nd->path); 3188 error = -ELOOP; 3189 break; 3190 } 3191 error = may_follow_link(&link, nd); 3192 if (unlikely(error)) 3193 break; 3194 nd->flags |= LOOKUP_PARENT; 3195 nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); 3196 error = follow_link(&link, nd, &cookie); 3197 if (unlikely(error)) 3198 break; 3199 error = do_last(nd, &path, file, op, &opened, pathname); 3200 put_link(nd, &link, cookie); 3201 } 3202 out: 3203 if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) 3204 path_put(&nd->root); 3205 if (base) 3206 fput(base); 3207 if (!(opened & FILE_OPENED)) { 3208 BUG_ON(!error); 3209 put_filp(file); 3210 } 3211 if (unlikely(error)) { 3212 if (error == -EOPENSTALE) { 3213 if (flags & LOOKUP_RCU) 3214 error = -ECHILD; 3215 else 3216 error = -ESTALE; 3217 } 3218 file = ERR_PTR(error); 3219 } 3220 return file; 3221 }